Javascript - 如何通过3种不同的属性类型对对象数组进行排序? (String,Integer,Boolean)

时间:2021-05-19 15:57:11

I have array of object:

我有一个对象数组:

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] },
];

I want to sort it like this, Sort By name ascending, and then no ascending and then by size1 if it not null.

我想按照这样排序,按名称升序排序,然后不升序,然后按size1,如果它不为空。

At first, I can sort it by name and no, but after that I don't know how to sort by size1 or size2. It should sorted by size1 first if it is not null. Here is my code to sort

首先,我可以按名称排序,但不是,但之后我不知道如何按size1或size2排序。如果它不为null,它应该首先按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;
        }
    });
}

Expected result

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] },
]

4 个解决方案

#1


4  

You would have to compare no in your first if:

你必须在第一个中比较否:

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;
        }
    });
}

#2


1  

You can try something like this:

你可以尝试这样的事情:

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)

#3


1  

You can do like this

你可以这样做

  1. For string comparison String.prototype.localeCompare()
  2. 用于字符串比较String.prototype.localeCompare()

  3. For number/Array length subtraction
  4. 对于数字/数组长度减法

DEMO

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;}

#4


1  

You can use a modified version of orderBy from 30 seconds of code (a project/website that I maintain), which also checks for null and orders accordingly:

您可以在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);

How orderBy works:

orderBy如何工作:

Uses Array.sort(), Array.reduce() on the props array with a default value of 0, use array destructuring to swap the properties position depending on the order passed. If no orders array is passed it sort by 'asc' by default.

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

#1


4  

You would have to compare no in your first if:

你必须在第一个中比较否:

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;
        }
    });
}

#2


1  

You can try something like this:

你可以尝试这样的事情:

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)

#3


1  

You can do like this

你可以这样做

  1. For string comparison String.prototype.localeCompare()
  2. 用于字符串比较String.prototype.localeCompare()

  3. For number/Array length subtraction
  4. 对于数字/数组长度减法

DEMO

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;}

#4


1  

You can use a modified version of orderBy from 30 seconds of code (a project/website that I maintain), which also checks for null and orders accordingly:

您可以在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);

How orderBy works:

orderBy如何工作:

Uses Array.sort(), Array.reduce() on the props array with a default value of 0, use array destructuring to swap the properties position depending on the order passed. If no orders array is passed it sort by 'asc' by default.

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