user1012181
user1012181

Reputation: 8726

Sort null values based on another variable in the object

I'm trying to sort a list of Objects in ascending order. But there are cases when the sort value is null and in that case, the value should be sorted alphabetically.

I tried to create the following code:

let items = [
  {
   name: 'Foo',
   Km: null
  },
  {
   name: 'Bar',
   Km: 4
  },
  {
   name: 'BarFoo',
   Km: null
  },
  {
   name: 'FooBar',
   Km: 1
  },
]

function sortNullValues(values) {

    values.sort(function (a, b) {
    if(a.Km === null) return 1
    if(b.Km === null) return -1
    if (a.Km < b.Km) return 1
        if (a.Km < b.Km) return -1
    if (a.name > b.name) return -1
        if (a.name < b.name) return 1
  })

  return values
}

console.log(sortNullValues(items))

But the null valued objects are not sorting alphabetically. https://jsfiddle.net/am7n61ou/56/

Current Output:

[
  {
   name: 'Bar',
   Km: 4
  },
  {
   name: 'FooBar',
   Km: 1
  },
  {
   name: 'Foo',
   Km: null
  },
  {
   name: 'BarFoo',
   Km: null
  }
]

Desired Output:

[
  {
   name: 'FooBar',
   Km: 1
  },
  {
   name: 'Bar',
   Km: 4
  },
  {
   name: 'BarFoo',
   Km: null
  },
  {
   name: 'Foo',
   Km: null
  }
]

Upvotes: 1

Views: 35

Answers (2)

Nina Scholz
Nina Scholz

Reputation: 386560

You could first sort the null values to bottom, sort by Km (null - nullis zero) or by string.

var array = [{ name: 'Foo', Km: null }, { name: 'Bar', Km: 4 }, { name: 'BarFoo', Km: null }, { name: 'FooBar',  Km: 1 }];

array.sort((a, b) => 
    (a.Km === null) - (b.Km === null) ||
    a.Km - b.Km ||
    a.name.localeCompare(b.name)
);

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

Upvotes: 3

nucleartux
nucleartux

Reputation: 1390

You function always returns -1 even if both values are null. I've fixed your code. You should check for null values and return different sorting.

Corrected code:

  values.sort(function (a, b) {
    if (a.Km === null && b.Km === null) {
      if (a.name > b.name) return 1
      if (a.name < b.name) return -1
        }
    if(a.Km === null) return 1
    if(b.Km === null) return -1
    if (a.Km < b.Km) return 1
        if (a.Km < b.Km) return -1
  })

Upvotes: 0

Related Questions