Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

lodash orderby with null and real values not ordering correctly

I have an Angular 2 typescript application that is using lodash for various things.

I have an array of objects that I am ordering using a property in the object...

_.orderBy(this.myArray, ['propertyName'], ['desc']);

This works well however my problem is that sometimes 'propertyName' can have a null value. These are ordered as the first item in a descending list, the highest real values then follow.

I want to make these null values appear last in the descending ordering.

I understand why the nulls come first.

Does anyone know how to approach this?

like image 771
Ben Cameron Avatar asked Dec 14 '16 09:12

Ben Cameron


People also ask

Does Lodash groupBy preserve order?

groupBy , but it does preserve the order of array-like collections, and that's probably unlikely to change. So the sub-items within groups would retain their original ordering, but the grouped key ordering may change, because they are object properties.

How do you use orderBy Lodash?

orderBy() method is similar to _. sortBy() method except that it allows the sort orders of the iterates to sort by. If orders are unspecified, then all values are sorted in ascending order otherwise order of corresponding values specifies an order of “desc” for descending or “asc” for ascending sort.

Is Lodash sort stable?

This method performs a stable sort, that is, it preserves the original sort order of equal elements. The iteratees are invoked with one argument: (value).

Is null in Lodash?

Lodash helps in working with arrays, strings, objects, numbers, etc. The _. isNull() method is used to find whether the value of the object is null. If the value is null then returns true otherwise it returns false.

How to sort Nulls first whilst ordering non-NULL values in descending order?

Correspondingly, to sort NULLs first whilst ordering non-NULL values in descending order, we can use the following query: The output of the above two queries will be identical to using the NULLS FIRST / NULLS LAST options in SQLite.

Does Lodash move data to the end of an array?

Thanks. Lodash 3.10.1: Lodash 3.6.0: Correct, is now moved to the end when sorted (ascending) so when sorting descending will be at the front of the array. Could you _.compact your results before sorting?

What is the Order of null values in SQLite?

In effect, Oracle considers NULL values larger than any non-NULL values. Unlike the above database types, SQLite considers NULLs to be smaller than any other value. If you sort a column with NULL values in ascending order, the NULLs will come first. Alternatively, if you add a DESC keyword to get a descending order, NULLs will appear last.

How to check if a string is null in orderby?

The _.orderBy () function's iteratees can use a method instead of a string. Check the value, and if it's null return an empty string. The check can be simple (like the one I've used), which converts all falsy values to an empty string:


3 Answers

The _.orderBy() function's iteratees can use a method instead of a string. Check the value, and if it's null return an empty string.

const myArray = [{ propertyName: 'cats' }, { propertyName: null }, { propertyName: 'dogs' }, { propertyName: 'rats' }, { propertyName: null }];

const result = _.orderBy(myArray, ({ propertyName }) => propertyName || '', ['desc']);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>

The check can be simple (like the one I've used), which converts all falsy values to an empty string:

propertyName || ''

If you need a stricter check, you can use the ternary operator, and handle just null values:

propertyName === null ? '' : propertyName

Edit: Example with multiple ordering:

const result = _.orderBy(myArray, (item) => [get(item, 'propertyName', 0), get(item, 'propertyName2')], ['desc', 'asc']);

This will order by propertyName then propertyName2.

If propertyName is undefined/null then its default order will be set to 0. (and therefore will be displayed at last because of desc ordering on the propertyName field). In such case, propertyName2 will therefore determine the ordering.

like image 193
Ori Drori Avatar answered Oct 10 '22 10:10

Ori Drori


The code I needed looks like this...

_.orderBy(this.myArray, [( o ) => { return o.myProperty || ''}], ['desc']); 
like image 22
Ben Cameron Avatar answered Oct 10 '22 10:10

Ben Cameron


Just for future reference to others you can do this to sort ascending with falsey values at the end.

items =>
  orderBy(
    items,
    [
      i => !!i.attributeToCheck,
      i => {
        return i.attributeToCheck ? i.attributeToCheck.toLowerCase() : ''
      }
    ],
    ['desc', 'asc']
  )
like image 5
infinity Avatar answered Oct 10 '22 12:10

infinity