简体   繁体   English

具有空值和实值的 lodash orderby 未正确排序

[英]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 to 0 .如果propertyName为 undefined/null,则其默认顺序将设置为0 (and therefore will be displayed at last because of desc ordering on the propertyName 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM