Javascript - 如何按 3 种不同的属性类型对对象数组进行排序? (字符串、整数、布尔值)

Posted

技术标签:

【中文标题】Javascript - 如何按 3 种不同的属性类型对对象数组进行排序? (字符串、整数、布尔值)【英文标题】:Javascript - How to sort array of object by 3 different attributes type? (String, Integer, Boolean) 【发布时间】:2019-02-06 09:05:00 【问题描述】:

我有一个对象数组:

var a = [
  "name": "BBB", "no": 2, "size1": [3], "size2": null ,
  "name": "AAA", "no": 5, "size1": null, "size2": [1] ,
  "name": "BBB", "no": 1, "size1": [2], "size2": null ,
  "name": "AAA", "no": 4, "size1": null, "size2": [1] ,
  "name": "BBB", "no": 1, "size1": null, "size2": [1] ,
  "name": "AAA", "no": 5, "size1": [2], "size2": null ,
  "name": "BBB", "no": 2, "size1": null, "size2": [1] ,
];

我想这样排序,按name升序排序,然后no升序排序,如果不为空则按size1。

一开始我可以按nameno排序,但之后我不知道如何按size1size2排序。如果不为空,则应首先按 size1 排序。 这是我要排序的代码

function sortObject(arrayObjects)
    arrayObjects.sort(function(a,b)
        if(a.name=== b.name)
            return (a.no - b.no);
         else if(a.name > b.name)
            return 1;
         else if(a.name < b.name)
            return -1;
        
    );

预期结果

var a = [
  "name": "AAA", "no": 4, "size1": null, "size2": [1] ,
  "name": "AAA", "no": 5, "size1": [2], "size2": null ,
  "name": "AAA", "no": 5, "size1": null, "size2": [1] ,
  "name": "BBB", "no": 1, "size1": [2], "size2": null ,
  "name": "BBB", "no": 1, "size1": null, "size2": [1] ,
  "name": "BBB", "no": 2, "size1": [3], "size2": null ,
  "name": "BBB", "no": 2, "size1": null, "size2": [1] ,
]

【问题讨论】:

size1null 时,你希望它做什么?你什么时候使用size2 是的,如果 size1 为空,那么我使用 size2。每个对象只有 Size1 或 Size2。我只需要先按 size1 排序,然后按 size2 排序。看起来像按名称和否分组 【参考方案1】:

您可以从 30 秒的代码(我维护的一个项目/网站)中使用 orderBy 的修改版本,它还会检查 null 并相应地订购:

var a = [
"name": "BBB", "no": 2, "size1": [3], "size2": null ,
"name": "AAA", "no": 5, "size1": null, "size2": [1] ,
"name": "BBB", "no": 1, "size1": [2], "size2": null ,
"name": "AAA", "no": 4, "size1": null, "size2": [1] ,
"name": "BBB", "no": 1, "size1": null, "size2": [1] ,
"name": "AAA", "no": 5, "size1": [2], "size2": null ,
"name": "BBB", "no": 2, "size1": null, "size2": [1] ,
];

const orderBy = (arr, props, orders) =>
  [...arr].sort((a, b) =>
    props.reduce((acc, prop, i) => 
      if (acc === 0) 
        const [p1, p2] = orders && orders[i] === 'desc' ? [b[prop], a[prop]] : [a[prop], b[prop]];
        acc = p1 === null ? 1 : p2 === null ? -1 : p1 > p2 ? 1 : p1 < p2 ? -1 : 0;
      
      return acc;
    , 0)
  );
  
 var aSorted = orderBy(a, ['name', 'no', 'size1', 'size2'], ['asc', 'asc', 'asc', 'asc']);
 
 console.log(aSorted);

orderBy 的工作原理:

props 数组上使用Array.sort()Array.reduce(),默认值为0,使用数组解构根据传递的顺序交换属性位置。如果没有传递orders 数组,则默认按'asc' 排序。

【讨论】:

【参考方案2】:

你可以这样做

    用于字符串比较String.prototype.localeCompare() 对于数字/数组长度减法

演示

const arr = [
"name": "BBB", "no": 2, "size1": [3], "size2": null ,
"name": "AAA", "no": 5, "size1": null, "size2": [1] ,
"name": "BBB", "no": 1, "size1": [2], "size2": null ,
"name": "AAA", "no": 4, "size1": null, "size2": [1] ,
"name": "BBB", "no": 1, "size1": null, "size2": [1] ,
"name": "AAA", "no": 5, "size1": [2], "size2": null ,
"name": "BBB", "no": 2, "size1": null, "size2": [1] ,
];

arr.sort((a, b) => 
  let check = a.name.localeCompare(b.name);
  if (check == 0) 
    check = a.no - b.no;
    if (check == 0) 
      check = (b.size1 || []).length - (a.size1 || []).length;
    
  
  return check;
);

console.log(arr)
.as-console-wrapper max-height: 100% !important;top: 0;

【讨论】:

【参考方案3】:

你可以试试这样的:

var a = [
  "name": "AAA", "no": 4, "size1": null, "size2": [1] ,
  "name": "AAA", "no": 5, "size1": [2], "size2": null ,
  "name": "AAA", "no": 5, "size1": null, "size2": [1] ,
  "name": "BBB", "no": 1, "size1": [2], "size2": null ,
  "name": "BBB", "no": 1, "size1": null, "size2": [1] ,
  "name": "BBB", "no": 2, "size1": [3], "size2": null ,
  "name": "BBB", "no": 2, "size1": null, "size2": [1] ,
]

a.sort(function(a, b)
  return  a.name.localeCompare(b.name) ||
          a.no - b.no ||
          (b.size1 === null) - (a.size1 === null) ||
          (b.size2 === null) - (a.size2 === null)
);

console.log(a)

【讨论】:

【参考方案4】:

您必须在您的第一个 if 中比较 no

function sortObject(arrayObjects)
    arrayObjects.sort(function(a,b)
        if (a.name=== b.name) 
            if (a.no === b.no) 
                // Determines which size to use for comparison
                const aSize = a.size1 || a.size2;
                const bSize = b.size1 || b.size2;

                return (aSize[0] - bSize[0]);
            
            return (a.no - b.no);
         else if (a.name > b.name) 
            return 1;
         else if (a.name < b.name) 
            return -1;
        
    );

【讨论】:

null 支票呢? null 的期望是什么? size1 可以是null。如果你执行null - [3] - 在这种情况下你会得到什么结果? 我刚刚使用问题的 cmets 中提供的详细信息更新了我的答案。 请注意,这些“大小”属性看起来像是数组,而不是普通数字。

以上是关于Javascript - 如何按 3 种不同的属性类型对对象数组进行排序? (字符串、整数、布尔值)的主要内容,如果未能解决你的问题,请参考以下文章

如何在javascript中按属性查找数组中的对象?

如何在javascript中按属性查找数组中的对象?

JavaScript按属性值对字典进行排序[重复]

JavaScript对象数组如何按指定属性和排序方

如何查询具有不同属性的模型

JavaScript中四种不同的属性检测方式比较