我有 2 个数组
a = [2,3,1,4]
b = [{id: 1}, {id: 2}, {id: 3}, {id: 4}]
我如何b
根据 进行排序a
?我想要的输出是
c = [{id: 2}, {id: 3}, {id: 1}, {id: 4}]
我更喜欢使用 Ramda 或常规 JS。
我有 2 个数组
a = [2,3,1,4]
b = [{id: 1}, {id: 2}, {id: 3}, {id: 4}]
我如何b
根据 进行排序a
?我想要的输出是
c = [{id: 2}, {id: 3}, {id: 1}, {id: 4}]
我更喜欢使用 Ramda 或常规 JS。
您可以为 JavaScript 的Array#sort
方法提供自定义比较函数。
使用自定义比较函数来保证排序顺序:
var sortOrder = [2,3,1,4],
items = [{id: 1}, {id: 2}, {id: 3}, {id: 4}];
items.sort(function (a, b) {
return sortOrder.indexOf(a.id) - sortOrder.indexOf(b.id);
});
目录:
- 如果 compareFunction(a, b) 返回小于 0,则将 a 排序到低于 b 的索引(即 a 在前)。
- 如果 compareFunction(a, b) 返回 0,则 a 和 b 彼此保持不变,但相对于所有不同元素进行排序。注意:ECMAscript 标准不保证这种行为,因此,并非所有浏览器(例如至少可以追溯到 2003 年的 Mozilla 版本)都尊重这一点。
- 如果 compareFunction(a, b) 返回大于 0,则将 b 排序到小于 a 的索引(即 b 在前)。
Hitmands 对上述解决方案做出了非常中肯的评论:
这种方法是 O(n2),并且会导致大型列表中的性能问题。最好先构建字典,使其保持 O(n)
因此,上述解决方案最终可能不会像您在大型输入中所需要的那样快。
要实施 Hitmands 的建议:
let sortOrder = [2,3,1,4],
items = [{id: 1}, {id: 2}, {id: 3}, {id: 4}];
const itemPositions = {};
for (const [index, id] of sortOrder.entries()) {
itemPositions[id] = index;
}
items.sort((a, b) => itemPositions[a.id] - itemPositions[b.id]);
Ramda真正解决了这些类型的问题。
在数据量较小的地方,我们可以使用一个简单的reduce函数和indexOf helper。
// match id of object to required index and insert
var sortInsert = function (acc, cur) {
var toIdx = R.indexOf(cur.id, a);
acc[toIdx] = cur;
return acc;
};
// point-free sort function created
var sort = R.reduce(sortInsert, []);
// execute it now, or later as required
sort(b);
// [ { id: 2 }, { id: 3 }, { id: 1 }, { id: 4 } ]
这适用于小型(ish)数据集,但每次迭代的indexOf操作通过减少对大型数据集效率低下。
我们可以通过从另一方面解决这个问题来解决这个问题,让我们使用groupBy根据对象的 id 对我们的对象进行分组,从而创建一个字典查找(好多了!)。然后我们可以简单地映射所需的索引并将它们转换为相应位置的对象。
这是使用这种方法的解决方案:
var groupById = R.groupBy(R.prop('id'), b);
var sort = R.map(function (id) {
return groupById[id][0];
});
sort(a);
// [ { id: 2 }, { id: 3 }, { id: 1 }, { id: 4 } ]
最后,这是另一个非常简洁的解决方案:
R.sortBy(R.pipe(R.prop('id'), R.indexOf(R.__, a)))(b);
// [ { id: 2 }, { id: 3 }, { id: 1 }, { id: 4 } ]
我喜欢您可以使用行为组合函数并将算法与其使用Ramda 所依据的数据分离的方式。您最终会得到非常易读且易于维护的代码。
使用 ES6 映射和查找
const a = [2,3,1,4];
const b = [{id: 1}, {id: 2}, {id: 3}, {id: 4}];
// map over a, find it in b and return
const c = a.map((i) => b.find((j) => j.id === i));
您可以c
在a
不使用的情况下创建基于b
:
var a = [2,3,1,4];
var c = [];
for(var i = 0; i < a.length; i++){
c.append({id:a[i]);
}
希望这可以帮助!
或者可能更简单
b.sort(function(obj1,obj2){
return a.indexOf(obj1.id) > a.indexOf(obj2.id)
});