【问题标题】:Sort array of objects based on a particular key recursively: Javascript基于特定键递归地对对象数组进行排序:Javascript
【发布时间】:2020-11-13 08:30:09
【问题描述】:

我有一个对象数组,格式如下:

var test = [
  {
    value: "Others",
    parentId: "",
    label: "Others",
    children: [
      {
        value: "user12",
        parentId: "Others",
        label: "bdefault51"
      },
      {
        value: "user11",
        parentId: "Others",
        label: "adefault50"
      }
    ]
  },
  {
    value: "Local",
    parentId: "",
    label: "local",
    children: [
      {
        value: "user56",
        parentId: "local",
        label: "bserver"
      },
      {
        value: "user78",
        parentId: "local",
        label: "aserver"
      }
    ]
  },
  {
    value: "Lab1",
    parentId: "",
    label: "lab1",
    children: [
      {
        value: "user157",
        parentId: "ent1",
        label: "enterprise45"
      },
      {
        value: "user139",
        parentId: "ent1",
        label: "enterprise37"
      },
      {
        value: "user136",
        parentId: "ent1",
        label: "enterprise56"
      }
    ]
  }
];

输出

 [
  {
    value: "Lab1",
    parentId: "",
    label: "lab1",
    children: [
      {
        value: "user139",
        parentId: "ent1",
        label: "enterprise37"
      },
      {
        value: "user157",
        parentId: "ent1",
        label: "enterprise45"
      },
      {
        value: "user136",
        parentId: "ent1",
        label: "enterprise56"
      }
    ]
  },
  {
    value: "Local",
    parentId: "",
    label: "local",
    children: [
      {
        value: "user78",
        parentId: "local",
        label: "aserver"
      },
      {
        value: "user56",
        parentId: "local",
        label: "bserver"
      }
    ]
  },
  {
    value: "Others",
    parentId: "",
    label: "Others",
    children: [
      {
        value: "user11",
        parentId: "Others",
        label: "adefault50"
      },
      {
        value: "user12",
        parentId: "Others",
        label: "bdefault51"
      },   
    ]
  }
];

我需要根据属性label 对对象进行排序。孩子们可以升到n级别,也需要label进行排序。

我尝试过的代码

for (var i = 0; i < test.length; i++) {
  test[i].children.sort((a, b) => {
    return b.label - a.label;
  });
}

//Tried with lodash also
let sorted = _.sortBy(test,"label");
let sorted1 = _.orderBy(test,"label","asc");
console.log(test); 

【问题讨论】:

  • 你期望b.label - a.label 是什么? "bdefault51" - "adefault50"?
  • 那么问题是什么?你说孩子可以生孩子吗?你可能想要return a.label.localeCompare(b.label)

标签: javascript arrays sorting ecmascript-6 ecmascript-5


【解决方案1】:

首先:您正在尝试像数字一样对字符串进行排序。这就是为什么它不起作用。将b.label - a.label 更改为b.label &gt; a.label,它必须工作(简单的解决方案):

for (var i = 0; i < test.length; i++) {
  test[i].children = test[i].children.sort((a, b) => {
    return b.label > a.label;
  });
}

如果您需要更高级的排序可能性:使用localeCompare 方法来比较字符串。

但通常修改现有数组是不好的方法。

更好的解决方案是创建一个递归排序函数并使用它来创建新的排序数组:

function sortArray(arr, key) {
  return arr
    .map(item => ({
      ...item,
      children: sortArray(item.children || [], key)
    }))
    .sort((a, b) => b[key] > a[key]);
}

const sortedArray = sortArray(test, "label");

【讨论】:

    【解决方案2】:

    您可以采用递归方法并迭代给定数组及其子属性。

    const
        sort = array => {
            array.sort((a, b) => a.label.localeCompare(b.label));
            array.forEach(({ children = [] }) => sort(children));
        };
    

    【讨论】:

    • 很好很好:)