繁体   English   中英

如何根据其他标签数组对带有标签的对象数组进行排序?

[英]How to sort an array of objects with labels according to other array of labels?

例如,我想对带有标签的对象数组进行排序

var arrayToBeSorted = [{label: 'firstLabel', value: 123}, {label: 'secondLabel', value: 456}, {label: 'thirdLabel', value: 789}]

和一个标签数组作为基线,例如

var labels = ['secondLabel', 'thirdLabel', 'fourthLabel', 'firstLabel']

现在我想对我的第一个数组进行排序,以便其中的对象遵循第二个数组labels中的标签顺序。

我知道带有自定义比较器的基本排序机制,例如

CustomComparator: function(a, b) {
  if (a[0].length > b[0].length) return -1;
  if (a[0].length < b[0].length) return 1;
  return 0;
}

但我不知道如何转换它。

在我的研究中,我在 ruby 编码的 stackoverflow 上找到了这个解决方案,但我不知道 javascript 中是否有类似的选项。

我感谢任何帮助,为此投入了相当多的时间。

您需要根据第二个数组为值提供优先级。 在这里,我们从第二个数组名称作为键和索引作为优先级构建一个 Map。 所以你可以使用Mapdefault valuesort

 var arrayToBeSorted = [{label: 'firstLabel', value: 123}, {label: 'secondLabel', value: 456}, {label: 'thirdLabel', value: 789}] var labels = ['secondLabel', 'thirdLabel', 'fourthLabel', 'firstLabel'] let mapper = new Map(labels.map((v, i) => [v, i + 1])) let final = arrayToBeSorted.sort((a, b) => { return (mapper.get(a.label) || Infinity) - (mapper.get(b.label) || Infinity) }) console.log(final)

有几种方法:

  1. 使用indexOf重复搜索labels数组

  2. 使用 map 因此查找 label 的索引更快

这是一个使用indexOf的示例(在 ES2015+ 中):

arrayToBeSorted.sort((a, b) => labels.indexOf(a.label) - labels.indexOf(b.label));

实时复制:

 var arrayToBeSorted = [{label: 'firstLabel', value: 123}, {label: 'secondLabel', value: 456}, {label: 'thirdLabel', value: 789}]; var labels = ['secondLabel', 'thirdLabel', 'fourthLabel', 'firstLabel']; arrayToBeSorted.sort((a, b) => labels.indexOf(a.label) - labels.indexOf(b.label)); console.log(arrayToBeSorted);

请注意,如果labels中不存在 label, indexOf将返回-1 ,这将使未知标签出现在结果的开头。 如果您希望它们放在最后,请检查-1并将其替换为Infinity

这是一个使用 map 来加快查找这些索引的示例(在 ES2015+ 中):

const map = new Map(labels.map((label, index) => [label, index]));
arrayToBeSorted.sort((a, b) => {
    let aindex = map.get(a.label);
    if (aindex === null) {
        aindex = -1; // Or Infinity if you want them at the end
    }
    let bindex = map.get(b.label);
    if (bindex === null) {
        bindex = -1; // ""
    }
    return aindex - bindex;
});

实时复制:

 var arrayToBeSorted = [{label: 'firstLabel', value: 123}, {label: 'secondLabel', value: 456}, {label: 'thirdLabel', value: 789}]; var labels = ['secondLabel', 'thirdLabel', 'fourthLabel', 'firstLabel']; const map = new Map(labels.map((label, index) => [label, index])); arrayToBeSorted.sort((a, b) => { let aindex = map.get(a.label); if (aindex === null) { aindex = -1; // Or Infinity if you want them at the end } let bindex = map.get(b.label); if (bindex === null) { bindex = -1; // "" } return aindex - bindex; }); console.log(arrayToBeSorted);

这是为了清楚起见并避免在回调中多次查找标签。 以 map 中的第二次 label 查找为代价可以更简洁:

const map = new Map(labels.map((label, index) => [label, index]));
arrayToBeSorted.sort((a, b) => {
    const aindex = map.has(a.label) ? map.get(a.label) : -1; // Or Infinity if you want them at the end
    const bindex = map.has(b.label) ? map.get(b.label) : -1; // "
    return aindex - bindex;
});

实时复制:

 var arrayToBeSorted = [{label: 'firstLabel', value: 123}, {label: 'secondLabel', value: 456}, {label: 'thirdLabel', value: 789}]; var labels = ['secondLabel', 'thirdLabel', 'fourthLabel', 'firstLabel']; const map = new Map(labels.map((label, index) => [label, index])); arrayToBeSorted.sort((a, b) => { const aindex = map.has(a.label)? map.get(a.label): -1; // Or Infinity if you want them at the end const bindex = map.has(b.label)? map.get(b.label): -1; // " return aindex - bindex; }); console.log(arrayToBeSorted);

它甚至可以是:

const map = new Map(labels.map((label, index) => [label, index]));
arrayToBeSorted.sort((a, b) =>
    (map.has(a.label) ? map.get(a.label) : -1) - (map.has(b.label) ? map.get(b.label) : -1)
);

...但对我来说,在调试等时这让生活变得太困难了。

您可以创建自定义订单并通过它订购:

 var arrayToBeSorted = [ {label: 'firstLabel', value: 123}, {label: 'secondLabel', value: 456}, {label: 'thirdLabel', value: 789} ]; let order = { secondLabel: 1, thirdLabel: 2, fourthLabel: 3, firstLabel: 4 }; arrayToBeSorted.sort((a, b) => { return order[a.label] - order[b.label]; }); console.log(arrayToBeSorted);

直接使用sort-array

const sortArray = require('sort-array')

const arrayToBeSorted = [
  {label: 'firstLabel', value: 123},
  {label: 'secondLabel', value: 456},
  {label: 'thirdLabel', value: 789}
]

sortArray(arrayToBeSorted, {
  by: 'label',
  order: 'labelOrder',
  customOrders: {
    labelOrder: ['secondLabel', 'thirdLabel', 'fourthLabel', 'firstLabel']
  }
})

console.log(arrayToBeSorted)

打印此 output:

[
  { label: 'secondLabel', value: 456 },
  { label: 'thirdLabel', value: 789 },
  { label: 'firstLabel', value: 123 }
]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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