orderBy not working with null values
jordanbrowneb opened this issue · comments
We're getting some really weird behavior when using orderBy
on arrays with null
in them.
Below is a test case running linq 3.2.1 on node 10.15.3.
const Enumerable = require('linq');
const data = ['2019-10-01', null, '2019-09-12', '2019-09-15', null];
const result = Enumerable.from(data).orderBy(x => x).toArray();
result.forEach(x => console.log(x));
Expected output:
null
null
2019-09-12
2019-09-15
2019-10-01
Actual output:
2019-10-01
null
2019-09-12
2019-09-15
null
Thanks in advance for any help you can provide.
This is the function used for comparison:
compare: function (a, b) {
return (a === b) ? 0
: (a > b) ? 1
: -1;
}
Values are reversed if (a>b)
.
Unfortunately comparing something with null always returns false.
console.log('2019-09-12' > null)
false
console.log('2019-09-12' < null)
false
One solution would be to pass a better lambda to orderBy
, causing the value to be sanitized before comparing:
const result = Enumerable.from(data).orderBy(x => (x===null) ? "" : x).toArray();
Thank you for your quick reply. Do you intend to change the library to better handle nulls like in this case? Or is the workaround you posted going to be the permanent solution?
Not sure yet...
array.sort()
does indeed sort the above values but it does so by converting nulls to strings.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
We can probably do the same for this library using some typeof
wizzardry, but it feels like a very specific scenario.
Gotcha. It's a fairly common use case for us ( e.g. calling .select(...)
to grab a nullable property then sorting it using .orderBy(...)
).
We were surprised that the order returned was not the same as when doing the equivalent calls in C# LINQ. C# will return the expected output I listed earlier.
This is the function used for comparison:
compare: function (a, b) { return (a === b) ? 0 : (a > b) ? 1 : -1; }
Values are reversed if
(a>b)
.
Unfortunately comparing something with null always returns false.console.log('2019-09-12' > null) false console.log('2019-09-12' < null) false
One solution would be to pass a better lambda to
orderBy
, causing the value to be sanitized before comparing:
const result = Enumerable.from(data).orderBy(x => (x===null) ? "" : x).toArray();
Now , you can set compare function , at 3.2.2
Issue: #74
const a= ['2019-10-01', null, '2019-09-12', '2019-09-15', null];
var cf = new Intl.Collator();
Enumerable.from(a).orderBy(x=>x, cf.compare).toArray()
output:
["2019-09-12", "2019-09-15", "2019-10-01", null, null]
You can prepare a custorm compare function to let null in front.
warning:
You should have a reasonable initialization parameter,otherwise the result may not be what you want.
see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Collator
Example:
var cf = new Intl.Collator();
cf.compare(1,2)
//=-1
cf.compare(15,2)
//=-1 (Expected = 1)