Sort Array of Objects by value of unknown keys

Viewed 674

I'm trying to sort an array of objects by its values and return the 3 keys with the highest value in descending order. The array is:

let obj = [
{'tom':4},
{'bill':5},
{'tina':6},
{'tim': 3}]

Solution I'm looking for: ['tina', 'bill', 'tom']

In case, there are more than three values, that fulfill the condition I would like to list them as well, like:

let obj = [
{'tom':4},
{'bill':5},
{'tina':6},
{'tim': 3},
{'jim':4]

Solution I'm looking for: ['tina', 'bill', 'tom', 'jim']

I tried to do something like:

Object.entries(obj).sort((a,b) => b[1] - a[1]).map(value => ({[value[0]]: value[1]}))

but couldn't figure out the right approach.

4 Answers
  1. First sort the array of objects by their values, (using .sort and Object.values.)
  2. Select the values of the top 3 items, (using .slice, .map and Object.values.)
  3. Select all the items from the original array that have values in the top 3 array, (using .reduce)

You should end up with an array of keys that have the top 3 highest values.

Here's what that looks like:

let obj = [
    {
        tom: 4,
    },
    {
        bill: 5,
    },
    {
        tina: 6,
    },
    {
        tim: 3,
    },
    {
        jim: 4,
    },
];

// An array of values of the Top 3 sorted objects
let top3 = obj
    .map((obj) => Object.values(obj)[0])
    .sort((a, b) => b - a)
    .slice(0, 3);
    

// An array the Top Keys that are found in t3
let topKeys = obj.reduce((acc, curr) => {
    if (top3.includes(Object.values(curr)[0])) acc.push(Object.keys(curr)[0]);
    return acc;
}, []);

console.log(topKeys);

let obj = [{
    'tom': 4
  },
  {
    'bill': 5
  },
  {
    'tina': 6
  },
  {
    'tim': 3
  },
  {
    'jim': 4
  }
]

let result = obj.map(object => {
  for (name in object) {
    return [name, object[name]]
  }
}).sort((a, b) => b[1] - a[1]).map(object => object[0])

console.log(result)

Step 1.

Using Array#reduce to create an object that looks like {[value: number]: Array<string>}, which will be automatically sorted due to the default object key sorting.

Step 2.

Using Object.values to get the list of values of the {[value: number]: Array<string>} object.

Step 3.

Using Array#slice to get the last 3 items.

Step 4.

Using Array#flat to convert the array from Array<Array<string>> to Array<string>.

let obj = [
  { 'tom': 4 },
  { 'bill': 5 },
  { 'tina': 6 },
  { 'tim': 3 },
  { 'jim': 4 }
];

var sortedObj = obj.reduce(function(result, item) {
  // get the name and value of the current object
  var key = Object.keys(item)[0], value = item[key];
  // get the list of names for that value
  var list = result[value];
  // if this is the first occurence of the value, create the array
  if (!list) result[value] = list = [];
  // add the name to the array
  list.push(key);
  return result;
}, {});

var sortedList = Object.values(sortedObj);

var last3 = sortedList.slice(sortedList.length - 3);

var result = last3.flat();

console.log(result);

You could

  • map the entries of the object,
  • sort the 2D array of entries based on the first entry's value
  • map to get the first value of each object

const input = [{ tom: 4 }, { bill: 5 }, { tina: 6 }, { tim: 3 }];

const output = input
                .map(Object.entries)
                .sort(([a], [b]) => b[1] - a[1])
                .map(([[name]]) => name);

console.log(output)

Related