[英]lodash orderby with null and real values not ordering correctly
I have an Angular 2 typescript application that is using lodash for various things.我有一个 Angular 2 typescript 应用程序,它使用 lodash 处理各种事情。
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.这很好用,但是我的问题是有时“propertyName”可以有一个空值。 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?有谁知道如何解决这个问题?
The _.orderBy()
function's iteratees can use a method instead of a string. _.orderBy()
函数的迭代器可以使用方法而不是字符串。 Check the value, and if it's null
return an empty string.检查该值,如果它为
null
,则返回一个空字符串。
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:如果需要更严格的检查,可以使用三元运算符,只处理
null
值:
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
.这将按
propertyName
然后propertyName2
排序。
If
propertyName
is undefined/null then its default order will be set to0
.如果
propertyName
为 undefined/null,则其默认顺序将设置为0
。 (and therefore will be displayed at last because ofdesc
ordering on thepropertyName
field).(因此,由于
propertyName
字段上的desc
排序,最终将显示)。 In such case,propertyName2
will therefore determine the ordering.在这种情况下,
propertyName2
将因此确定排序。
我需要的代码看起来像这样......
_.orderBy(this.myArray, [( o ) => { return o.myProperty || ''}], ['desc']);
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']
)
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']
)
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] : "";
};
})),
);
mine looks like this.我的看起来像这样。 PropName and sort are both variables in my solution
PropName 和 sort 在我的解决方案中都是变量
return _.orderBy( myarray, [
( data ) => {
if ( data[propName] === null ) {
data[propName] = "";
}
return data[propName].toLowerCase();
}
], [sort] );
I wanted tolowercase because otherwise the sorting is not correct if different casings我想小写,否则如果不同的大小写排序不正确
I created a function for this (ts code):我为此创建了一个函数(ts代码):
const orderByFix = (array: any[], orderKeys: string[], orderDirs: ('asc' | 'desc')[]) => {
const ordered = orderBy(array, orderKeys, orderDirs);
const withProp = ordered.filter((o) => orderKeys.every(k => o[k]));
const withoutProp = ordered.filter((o) => !orderKeys.every(k => o[k]));
return [...withProp, ...withoutProp];
};
I've extended gwendall's answer to also handle case when "order keys" are functions ( _.orderBy
allows that)我已经扩展了 gwendall 的答案以处理“订单键”是函数时的情况(
_.orderBy
允许)
const orderByFix = (
array: any[],
orderKeys: (string | ((o: any) => any))[],
orderDirs: ('asc' | 'desc')[]
) => {
const ordered = orderBy(array, orderKeys, orderDirs)
const withProp = ordered.filter((o) =>
orderKeys.every((k) => {
if (typeof k === 'string') {
return o[k]
} else if (typeof k === 'function') {
return k(o)
} else {
throw Error(`Order key must be string or function not ${typeof k}`)
}
})
)
const withoutProp = ordered.filter(
(o) =>
!orderKeys.every((k) => {
if (typeof k === 'string') {
return o[k]
} else if (typeof k === 'function') {
return k(o)
} else {
throw Error(`Order key must be string or function not ${typeof k}`)
}
})
)
return [...withProp, ...withoutProp]
}
We can split the array into two: one - with empty values, the other one - without.我们可以将数组分成两部分:一个 - 有空值,另一个 - 没有。 Then sort the array without nulls and append the array with nulls at the end [...rows] creates copy of the array to avoid messing up original array that my still be used somewhere else in the aplication
然后对没有空值的数组进行排序,并在末尾添加空值 [...rows] 创建数组的副本,以避免弄乱我仍在应用程序中其他地方使用的原始数组
static doSort(rows, fieldName, sortDirection, nullslast) { if (!nullslast) { return _.orderBy([...rows], [fieldName], [sortDirection]); } const withoutNulls = []; const withNulls = []; for (let row of rows) { (row[fieldName] === null ? withNulls : withoutNulls).push(row); } return _.orderBy([...withoutNulls], [fieldName], [sortDirection]).concat(withNulls); }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.