基于另一个对象数组的属性值对数组进行排序

3

假设我有一个对象数组:

var list = [
       { name: "A", distance: 1},
       { name: "B", distance: 2},
       { name: "C", distance: 3},
       { name: "D", distance: 4},
       { name: "E", distance: 5},
       { name: "F", distance: 6},
       { name: "G", distance: 7},
       { name: "H", distance: 8} 
    ];

如果我有另一个类似于这样的数组:

var disturbed = ["G", "B", "C", "F"];

我该如何根据“list array”中的“distance property”对“disturbed array”进行排序,类似于以下方式:
["B", "C", "F", "G"];

编辑:我已经尝试了这段代码,但没有成功:

items = [ 
       { name: "A", distance: 1},
       { name: "B", distance: 2},
       { name: "C", distance: 3},
       { name: "D", distance: 4},
       { name: "E", distance: 5},
       { name: "F", distance: 6},
       { name: "G", distance: 7},
       { name: "H", distance: 8}
]

sorting = [ 1, 2,3,4,5,6,7,8,9,10 ];
result = []
for (let i = 0; i < items.length; i++){
sorting.forEach(function(key) {
    var found = false;
    items = items.filter(function(item) {

        if(!found && items[i].distance == key) {
            result.push(item);
            found = true;
            return false;
        } else 
            return true;
    })
})

result.forEach(function(item) {
    document.writeln(item[i]) 
})
}

如何根据另一个对象数组的属性值对数组进行排序


预期输出是什么? - ellipsis
https://dev59.com/OKzka4cB1Zd3GeqP1wO6 - Roope
3个回答

4
您可以使用.reduce()将列表数组转换为对象,然后根据此对象进行排序。
演示:

var list = [
       { name: "A", distance: 1},
       { name: "B", distance: 2},
       { name: "C", distance: 3},
       { name: "D", distance: 4},
       { name: "E", distance: 5},
       { name: "F", distance: 6},
       { name: "G", distance: 7},
       { name: "H", distance: 8} 
    ];
    
var disturbed = ["G", "B", "C", "F"];
    
var sort = list.reduce((acc, cur) => {
  acc[cur.name] = cur.distance;
  return acc;
}, {});

disturbed.sort((a, b) => sort[a] - sort[b]);

console.log(disturbed)


3
你可以使用 .find() 来查找具有指定 name 属性且与你在 distributed 中的元素匹配的对象。一旦你得到了这个对象,你就可以获取 distance 属性并计算差异以进行排序:

const list = [
  { name: "A", distance: 1},
  { name: "B", distance: 2},
  { name: "C", distance: 3},
  { name: "D", distance: 4},
  { name: "E", distance: 5},
  { name: "F", distance: 6},
  { name: "G", distance: 7},
  { name: "H", distance: 8} 
];

const disturbed = ["G", "B", "C", "F"];

const res = disturbed.sort((a, b) => {
  const {distance: d_a} = list.find(({name}) => name === a);
  const {distance: d_b} = list.find(({name}) => name === b);
  return d_a - d_b;
});

console.log(res);

一个更加高效的方法是使用 new Map 创建一个映射,然后在从映射中取出的键上使用 .map(),最后使用 .sort() 进行排序:

const list = [
  { name: "A", distance: 1},
  { name: "B", distance: 2},
  { name: "C", distance: 3},
  { name: "D", distance: 4},
  { name: "E", distance: 5},
  { name: "F", distance: 6},
  { name: "G", distance: 7},
  { name: "H", distance: 8} 
];
const disturbed = ["G", "B", "C", "F"];

const lut = new Map(list.map(({name, distance}) => [name, distance]));
const res = disturbed.sort((a, b) => lut.get(a) - lut.get(b));
console.log(res);


1
.find inside a sort is very inefficient though, something like O(log n² * n²) - Jonas Wilms
@JonasWilms,是的,我同意这不是很有效率。我本来想提出更好的方法,但_Cuong Le Ngoc_已经提供了。 - Nick Parsons

3
你可以使用sort方法来实现这个功能。
var list = [
       { name: "A", distance: 1},
       { name: "B", distance: 2},
       { name: "C", distance: 3},
       { name: "D", distance: 4},
       { name: "E", distance: 5},
       { name: "F", distance: 6},
       { name: "G", distance: 7},
       { name: "H", distance: 8} 
    ];

var disturbed = ["G", "B", "C", "F"];

disturbed.sort((a, b) => {
    var itemA = list.find(item => item.name === a);
    var itemB = list.find(item => item.name === b);
    return itemA.distance - itemB.distance;
});

disturbed.forEach(function(item) {
    document.writeln(item[i]) 
})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接