0

I'm trying to sort an array of objects by a key in a particular position. The only problem is that each object has a different key name.

here is an example of an object i'm trying to sort:

let data = [
  {name: "James", x: 3, }, 
  {name: "Thomas", y: 1}, 
  {name: "Zack", z: 2}
];

I'm trying to sort it by the 2nd key so the order should be

    [
      {name: "James", x: 3, }, 
      {name: "Zack", z: 2},
      {name: "Thomas", y: 1} 
    ];

here is how I'm trying to do it:

let data = [
      {name: "James", x: 3, }, 
      {name: "Thomas", y: 1}, 
      {name: "Zack", z: 2}
    ];

data.sort((a, b) => {
  let key1 = Object.keys(a)[1];
  let key2 = Object.keys(b)[1];
  return a[key1] > b[key2]
  });
console.log(data)

Here is my jsbin

https://jsbin.com/lihefodoni/edit?html,js,console

Not sure why it's not working. I'm trying to do this in my react Application so I don't know if there's something different I need to do?

11
  • 1
    Urgh. There is no such thing as "the second key". Key value pairs in objects are not really ordered. Commented Jul 4, 2019 at 20:32
  • don't objects in javascript retain their order? @JonasWilms Commented Jul 4, 2019 at 20:35
  • To hammer @JonasWilms point home. The Object.keys() documentation says: "in the same order as we get with a normal loop.". Moving on to the for...in documentation: "A for...in loop iterates over the properties of an object in an arbitrary order (see the delete operator for more on why one cannot depend on the seeming orderliness of iteration, at least in a cross-browser setting)." Commented Jul 4, 2019 at 20:37
  • In ES6+ environments, yes, order is preserved, but it's not guaranteed in ES5. Best not to rely on it Commented Jul 4, 2019 at 20:37
  • 1
    @JonasWilms—specifications are hard to write, I think they're doing an OK job. I wish they'd include references for when particular features or parts are added. That way I don't have to go hunting through old specs to find when they've changed. :-) Commented Jul 5, 2019 at 22:17

2 Answers 2

6

The .sort callback expects a number as a return value, not a Boolean (as the < operator will evaluate to). Return the numeric difference instead:

let data = [
      {name: "James", x: 3, }, 
      {name: "Thomas", y: 1}, 
      {name: "Zack", z: 2}
    ];

data.sort((a, b) => {
  let key1 = Object.keys(a)[1];
  let key2 = Object.keys(b)[1];
  return b[key2] - a[key1]
});
console.log(data)

To make sorting more reliable, .find the entry whose key is not name:

let data = [
      {name: "James", x: 3, }, 
      {name: "Thomas", y: 1}, 
      {name: "Zack", z: 2}
    ];

data.sort((a, b) => {
  const aEntry = Object.entries(a).find(([key]) => key !== 'name');
  const bEntry = Object.entries(b).find(([key]) => key !== 'name');
  return bEntry[1] - aEntry[1];
});
console.log(data)

Sign up to request clarification or add additional context in comments.

6 Comments

thanks! but i'm wondering why something like this works then? data = [{x: 1}, {x: 3} ,{x: 2}]; data.sort((a, b) => { return a.x > b.x });
Because you have to tell .sort about three different cases. a is before b, b is before a, and a and ` b` are the same. A Boolean can only represent two states: true or false, it cannot represent three states. Returning a boolean will never work reliably. Your example works by accident, shuffling the array would also result in the right result sometimes.
@james It doesn't: jsfiddle.net/w72bucdp 0: {x: 1} 1: {x: 3} 2: {x: 2}
huh that's so weird. it works fine in the javascript repl website but fails on jsfiddle @Snow
Thats not weird. If you change the engine, the implementation changes. If you use the API in an unspecified way, then you get unspecified results.
|
0

You could exclude the unwanted key and take the values of the object. it works by taking the only item without index.

let data = [{ name: "James", x: 3 }, { name: "Thomas", y: 1 }, { name: "Zack", z: 2 }];

data.sort(({ name, ...a }, { name: _, ...b }) => Object.values(b) - Object.values(a));

console.log(data)
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.