admin管理员组

文章数量:1278949

I can define an array of numbers and sort them like this

var array = ['2', undefined, '1'];
array.sort((a, b) => a - b);
console.log(array);

I can define an array of numbers and sort them like this

var array = ['2', undefined, '1'];
array.sort((a, b) => a - b);
console.log(array);

The output is 1, 2, null.

I have an array of objects that can include a number property, which I can define like this. Not all objects have the number property. Now I want to sort this array of objects by the number property. So I tried this:

var array = [
  { number: 2 },
  {},
  { number: 1 }
];
array.sort((a, b) => a.number - b.number);
console.log(array);

The output is not what I want. I get 2, undefined, 1.

If all objects in the array have the number property defined, the same sort function produces 1, 2, which is the result I would expect.

var array = [
  { number: 2 },
  { number: 1 }
];
array.sort((a, b) => a.number - b.number);
console.log(array);

So my question is, what is the best way to sort an array of objects by a property, where the property is not always defined. The intended result is that the objects are ordered by the property (number), with objects that do not define that property at the end of the array.

My only solution so far is to iterate the set, and if the property is not defined, set the property to 0 or null. I can then pass the object array to the sort function and it works as I want. Is there a better way than this?

Jfiddle: https://jsfiddle/t2r6z13e/1/

Share Improve this question edited May 26, 2019 at 11:29 F_SO_K asked May 26, 2019 at 11:10 F_SO_KF_SO_K 14.9k5 gold badges62 silver badges90 bronze badges
Add a ment  | 

6 Answers 6

Reset to default 6

You can return the difference between the existence of a number property on each object being pared, OR return the difference in their number properties (in the case that both objects have said properties):

var array = [
  { number: 2 },
  {},
  { number: 1 }
];

array.sort((a, b) => {
  const aHas = typeof a.number !== 'undefined';
  const bHas = typeof b.number !== 'undefined';
  return (bHas - aHas) || (aHas === true && a.number - b.number) || 0;
});
console.log(array);

The explanation is in the ments:

let array = [
  {},
  { number: 2 },
  {},
  { number: 1 }
];

array.sort((a, b) => {
  // two undefined values should be treated as equal ( 0 )
  if( typeof a.number === 'undefined' && typeof b.number === 'undefined' )
    return 0;
  // if a is undefined and b isn't a should have a lower index in the array
  else if( typeof a.number === 'undefined' )
    return 1;
    // if b is undefined and a isn't a should have a higher index in the array
  else if( typeof b.number === 'undefined' )
    return -1;
    // if both numbers are defined pare as normal
  else
    return a.number - b.number;
});

console.log( array );

You can provide defaults for array elements with object spreads: {default, ...item}

var array = [
  { number: 2 },
  {},
  { number: 1 },
  {},
  { number: 0 },
];

array.sort((a, b) => (
    {number: Number.MAX_VALUE, ...a}.number -
    {number: Number.MAX_VALUE, ...b}.number));

console.log(array);

If your target doesn't support object spreads yet, replace them with Object.assign.

A bit unreadable :

var array = [ { number: 2 }, { }, { number: 1 } ];

array.sort((a, b) => 'number' in a ? 'number' in b ? a.number - b.number : -1 : 1);

console.log(array);

Or maybe a bit more readable :

var array = [ { number: 2 }, { }, { number: 1 } ];

array.sort((a, b) => !('number' in a) ? 1 : !('number' in b) ? -1 : a.number - b.number);

console.log(array);

If pareFunction is supplied, all non-undefined array elements are sorted according to the return value of the pare function (all undefined elements are sorted to the end of the array, with no call to pareFunction).

In your code, in case of array with number sort function does not call for item with undefined value; while in case of array with object, object is defined but obj.number is not defined, so sort function get call for blank({}) object also and required to add undefined check for number in sort function.

The easiest and cleaner way

var array = [
  { number: 2 },
  {},
  { number: 1 }
];
array.sort((a, b) => (a.number == undefined ? Number.MAX_VALUE : a.number) - (b.number  == undefined ? Number.MAX_VALUE : b.number) );

console.log(array);

本文标签: Javascript Sort object array by number properties which include undefinedStack Overflow