3

CASE 1:

let items = [
  { name: "Edward", value: 21 },
  { name: "Shane", value: 37 },
  { name: "Daniel", value: 45 },
  { name: "Daniel", value: -12 },
  { name: "Magnetic", value: 13 },
  { name: "Magnetic", value: 37 },
];

items.sort(function (a, b) {
  if (a.name<b.name) {
    return -1;
  }
  if (a.name>b.name) {
    return 1;
  }
  // names must be equal
  return 0;
});

console.log(items);

CASE 2:

let items = [
  { name: "Edward", value: 21 },
  { name: "Shane", value: 37 },
  { name: "Daniel", value: 45 },
  { name: "Daniel", value: -12 },
  { name: "Magnetic", value: 13 },
  { name: "Magnetic", value: 37 },
];

items.sort(function (a, b) {
  if (a.name<b.name) {
    return -1;
  }
  if (a.name>b.name) {
    return 1;
  }
  // no case for equal names
});

console.log(items);

CASE 3:

items.sort(function (a, b) {
  return a.name < b.name ? -1 : 1;
});

All three return the following

[
  { name: 'Daniel', value: 45 },
  { name: 'Daniel', value: -12 },
  { name: 'Edward', value: 21 },
  { name: 'Magnetic', value: 13 },
  { name: 'Magnetic', value: 37 },
  { name: 'Shane', value: 37 }
]

All the above mentioned snippets return the same result, but there's definitely some example where all these return different results (Which I don't know). I wanted to know what happens when there's no return condition for the names being equal.

UPDATE: I've added a case 3 to the original question, actually case 1 and case 2 behave similarly because case 2 returns undefined when names are equal. But in case 3 where I use ternary operator it doesn't return undefined but still the answer remains the same. HOW?

14
  • "but there's definitely some example where both these return different results" - Don't you think those examples would be more meaningful for this question? Commented Oct 2, 2020 at 14:14
  • 2
    In this case the result will be the same. If the compare function returns undefined, which converts to NaN when convert to a number, then that value is converted to 0. ecma-international.org/ecma-262/10.0/#sec-sortcompare Commented Oct 2, 2020 at 14:17
  • 1
    This I can simplify to the below ternary expression: nameA < nameB ? -1 : 1 that's not correct. the corrct ternary expression for that function is nameA < nameB ? -1 : nameA > nameB ? 1 : undefined. Check out localeCompare Commented Oct 2, 2020 at 14:19
  • 1
    You are comparing objects..... does not make any sense. Commented Oct 2, 2020 at 14:43
  • 2
    @SomShekharMukherjee "but using ternary operator also returns the same result why?" I heavily suggest you read the link I posted. What you've done is conflated two of the states (equality and bigger than) into one (bigger than). You can expect odd sorting at times that is dependent on the browser and the dataset you use. So, it's going to be incorrect in some cases, but it's going to be very hard to find out which ones and why. Commented Oct 2, 2020 at 14:43

2 Answers 2

1

The main issue with your code is you are comparing Objects which makes no sense. So you should do sorting on a property in the object. Look at what the tests do.

var a = { foo: 1 };
var b = { foo: 2 };

console.log("a > b", a > b);
console.log("a > b", a < b);
console.log("a == b", a == b);

So in your sort you are literally have the same result in each check. It makes no sense. You need to look at the data in the object. You should be checking for 3 states 1) SAME, 2) Greater, and 3) Less Than.

When you do not return correct values for each state, you may run into browser sorting items differently each time. In your case you are not returning anything when it is equal and that will be seen as undefined and that us a falsely value so should probably be 0 which is equal. When you are just returning 1 and -1, you are making the browser do a lot more work since it is getting different values every time is makes a comparison. That will cause sort order to differ and can make it take extra long since it makes extra calculations.

let items = [
  { name: "Car", value: 100 },
  { name: "Apple", value: 21 },
  { name: "Car", value: 13 },
  { name: "Far", value: 37 },
  { name: "Apple", value: 10 },
  { name: "Bar", value: 45 }
];


items.sort( function (a, b) {

  // if names are equal lets sort on value
  if (a.name === b.name) {
    if (a.value === b.value) {
      return 0;
    } else if (a.value > b.value) {
      return 1;
    } else {
      return -1;
    }
  }
  else if (a.name > b.name) {
    return 1;
  }
  else {
    return -1;
  }
});

console.log(items);

Code cleaned up

let items = [
  { name: "Car", value: 100 },
  { name: "Apple", value: 21 },
  { name: "Car", value: 13 },
  { name: "Far", value: 37 },
  { name: "Apple", value: 10 },
  { name: "Bar", value: 45 }
];

items.sort( function (a, b) {

  // if names are equal lets sort on value
  if (a.name === b.name) {
    if (a.value === b.value) {
      return 0;
    } else {
      return (a.value > b.value) ? 1 : -1;
    }
  } else {
    return a.name.localeCompare(b.name);
  }
});

console.log(items);

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

2 Comments

The final code can be made a lot shorter via (a, b) => a.name.localeCompare(b.name) || (a.value - b.value)
Comparing objects was a typo, I just updated my question, so if you update your answer I can accept your answer.
0

If you don't specify a return for a function it returns undefined

function f() {
  // no return specified
}

let x = f(); // undefined

Now undefined is a falsy value, i.e. it can be coerced to false or 0. So although you're not explicitly returning 0, you're returning undefined which can sometimes work like 0

Another way to write this would be

items.sort(function (a, b) {
  if (nameA < nameB) {
    return -1;
  }
  if (nameA > nameB) {
    return 1;
  }
  
  // return "undefined" if it gets to this line
});

2 Comments

To be more precise -> 22.1.3.27.1 Runtime Semantics: SortCompare ( x, y ): .sort() calls ToNumber() on the result of the compare function (step 4a). In the case of undefined ToNumber() will return NaN which will be replaced with +0 (step 4b)
Okay but what if I use a ternary operator, in that case there's no undefined, but still it gives the same result, how? I've updated my question

Your Answer

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