2

My question is kinda linked to this one, but one step more complex : lodash orderby with null and real values not ordering correctly

Basically I have something like this :

let objs = [{x: {y: 1, z: 2}, a: 3}, {x: null, a: 4}];
let sortKeys = ['x.y', 'a']; //this is dynamic, can have multiple fields

The user can pass different values for sorting, like x.y or just a and sometimes x is null. So when I use the normal _.orderBy(objs, sortKeys, ['desc']) it shows null values first.

How can I do so that the null values appears last?

HRK44
  • 2,382
  • 2
  • 13
  • 30

2 Answers2

0

This solution partitions the array to values that are null or undefined (unsortable) via _.isNil(). It then sorts the sortable items, and concats the unsortable to the end:

const { partition, get, isNil, orderBy } = _;

const fn = (arr, key, order) => {
  const [unsortable, sortable] = partition(arr, o => isNil(get(o, key)));
  
  return orderBy(sortable, key, order)
    .concat(unsortable);
}

const objs = [{x: {y: 1, z: 2}, a: 3}, {x: {y: 4, z: 2}, a: 3}, {x: null, a: 4}];

const result = fn(objs, 'x.y', 'desc');

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
0

Pure ES6 solution would look like this:

let objs = [{x: {y: 1, z: 2}, a: 3}, {x: null, a: 4}];

objs.sort(({x: x1}, {x: x2}) => {
  const y1 = x1 === null ? Infinity : x1.y;
  const y2 = x2 === null ? Infinity : x2.y;
  
  return y1 - y2;
});

console.log(objs);

null's are simply weighted at a maximum possible value and sorted accordingly.

Alex Lomia
  • 6,705
  • 12
  • 53
  • 87