lodash orderby with null and real values not ordering correctly
Solution 1
The code I needed looks like this...
_.orderBy(this.myArray, [( o ) => { return o.myProperty || ''}], ['desc']);
Solution 2
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 to0
. (and therefore will be displayed at last because ofdesc
ordering on thepropertyName
field). In such case,propertyName2
will therefore determine the ordering.
Solution 3
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']
)
Solution 4
This will put bad values at the bottom, and it differentiates between numbers and strings.
const items = [] // some list
const goodValues = isAscending => ({ value }) => {
if (typeof value !== 'string' && isNaN(value)) {
return isAscending ? Infinity : -Infinity
}
return value || ''
}
const sortedItems = orderBy(
items,
[goodValues(isAscending), 'value'],
[isAscending ? 'asc' : 'desc']
)
Solution 5
This worked for me
orders = [{id : "1", name : "test"}, {id : "1"}];
sortBy = ["id", "name"];
orderby(
orders,
sortBy.map(s => {
return (r: any) => {
return r[s] ? r[s] : "";
};
})),
);
Ben Cameron
I'm a .net, JavaScript, and Angular developer based in London UK. I love to dev.
Updated on June 11, 2022Comments
-
Ben Cameron almost 2 years
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?
-
Ben Cameron over 7 yearsVery close, thank you. I've posted the full solution below.
-
Ori Drori over 7 yearsWhy do you need all the extra stuff
[( o ) => { return o.myProperty || ''}]
? My solution works out of the box. See the snippet. Just replacepropertyName
with the name of the property. -
Ben Cameron over 7 yearsIt didn't seem to work for me the way you had it but it did the way I had it. Maybe its a lodash thing or something. In any case the problem is solved now. Thanks for your help.
-
Ori Drori over 7 yearsWeird. Maybe typescript doesn't like it.
-
stallingOne almost 6 yearsthis still sorts nulls abode in asc order, is there a ways have null always at end ?
-
stallingOne almost 6 yearsthis still sorts nulls first in 'asc' order, is there a ways have null always at end ?
-
Ori Drori almost 6 years@stallingOne - it's not an elegant solution, but you can replace it with some later characters, such as a sequence of tildes - ~~~~~~~~~~~~. A case like this is better handled with the JS sort.
-
alextouzel almost 5 years@stallingOne i know this is old but for anyone trying to achieve this you can try _.orderBy(this.myArray, o => o || undefined)
-
Vadorequest over 4 yearsShould be the accepted answer. @BenCameron would you mind accept it?