Javascript 根据另一个ID数组对对象数组进行排序
我有两个数组Javascript 根据另一个ID数组对对象数组进行排序,javascript,ramda.js,Javascript,Ramda.js,我有两个数组 a = [2,3,1,4] b = [{id: 1}, {id: 2}, {id: 3}, {id: 4}] 如何根据a对b进行排序?我期望的输出是 c = [{id: 2}, {id: 3}, {id: 1}, {id: 4}] 我更喜欢使用Ramda或常规JS。您可以根据a创建c,而不必使用b: var a = [2,3,1,4]; var c = []; for(var i = 0; i < a.length; i++){ c.append({id:a[
a = [2,3,1,4]
b = [{id: 1}, {id: 2}, {id: 3}, {id: 4}]
如何根据a
对b
进行排序?我期望的输出是
c = [{id: 2}, {id: 3}, {id: 1}, {id: 4}]
我更喜欢使用Ramda或常规JS。您可以根据
a
创建c
,而不必使用b
:
var a = [2,3,1,4];
var c = [];
for(var i = 0; i < a.length; i++){
c.append({id:a[i]);
}
var a=[2,3,1,4];
var c=[];
对于(变量i=0;i
希望这有帮助!此解决方案使用辅助对象c
作为索引
{
"1": 2,
"2": 0,
"3": 1,
"4": 3
}
var a=[2,3,1,4],
b=[{id:1},{id:2},{id:3},{id:4}],
c=a.reduce(函数(r,a,i){
r[a]=i;
返回r;
}, {});
b、 排序(函数(x,y){
返回c[x.id]-c[y.id];
});
document.write(''+JSON.stringify(b,0,4)+'');
或者更简单一些
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);
});
纯javascript,使用数组的一些方法(
ES2015
标准)
var a=[2,3,1,4];
var b=[{id:1},{id:2},{id:3},{id:4}];
var c=[];
a、 forEach(el=>c.push(b.find(e=>e.id==el));
document.write(JSON.stringify(c,0,2));
您可以为JavaScript的方法提供自定义比较函数
使用自定义比较功能确保排序顺序:
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]);
:
- 如果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的建议:
var a = [2,3,1,4];
var b = [{id: 1}, {id: 2}, {id: 3}, {id: 4}]
R.find( R.propEq('id', a[0]), b )
R.values(R.mapObjIndexed( (num, key, obj) => R.find( R.propEq('id', a[key]), b ) , b))
使用Ramda,您必须通过mapObjIndexed函数将b中的对象映射到它们的索引,然后搜索a中的值。您可以尝试一下 对于这些类型的问题真的很有帮助 如果数据的大小很小,我们可以使用一个简单的函数和助手 这对于小型(ish)数据集很有效,但对于大型数据集,通过缩减每次迭代的操作都是低效的 我们可以通过从另一方面解决这个问题来解决这个问题,让我们使用根据对象id对对象进行分组,从而创建字典查找(更好!)。然后我们可以简单地遍历所需的索引,并将它们转换到该位置对应的对象 以下是使用这种方法的解决方案:
R.sortBy(R.pipe(R.prop('id'), R.indexOf(R.__, a)))(b);
// [ { id: 2 }, { id: 3 }, { id: 1 }, { id: 4 } ]
最后,这是另一个非常简洁的解决方案:
const sortBy = (array, values, key = 'id') => ((map) => values.reduce((a,i) =>
a.push(map[i]) && a,[]))(array.reduce((a,i) => (a[i[key]] = i) && a, {}));
我喜欢你用行为组合函数,并将算法与它所使用的数据分离的方式。你得到的代码可读性强,易于维护。非常好的解决方案。只需保留在这里以备将来使用:) 用法
这里有一个使用Ramda的替代构造,它可能更简洁一些,并且这些函数很容易用于其他用途
const{indexBy,prop,map,flip}=R
常数a=[2,3,1,4]
常数b=[{id:1},{id:2},{id:3},{id:4}]
const toIndexById=indexBy(prop('id'))
常量findIndexIn=翻转(道具)
常数c=map(findIndexIn(toindexbyd(b)),a)
控制台日志(c)
我将对的解决方案进行迭代
这里正确的方法是翻转问题,而不是
“根据b
给出的顺序排序a
”,
我宁愿“用来自a
的数据丰富b
”
这使您可以将此函数的时间复杂度保持在O(n)
,
而不是将其提升到O(n2)
const pickById=R.pipe(
R.indexBy(R.prop('id')),
右翻转(右支撑),
);
const exprich=R.useWith(R.map,[pickById,R.identity]);
// =====
常量数据=[2,3,1,4];
const source=[{id:1},{id:2},{id:3},{id:4}];
console.log(
丰富(来源、数据),
);
使用ES6映射并查找
真正的
b
对象是否包含除id
之外的任何内容?可能的重复可以使sortInsert
成为一个纯函数吗?:)我不认为Ramda在这里很出色tbh,我认为这些解决方案的可读性不如纯JS替代方案……可能不完全是问题所要求的,但仍然是一个有用的人目的跳出框框思考此方法是O(n2)
,在大列表中会导致性能问题。最好先构建字典,使其保持O(n)
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 } ]
const sortBy = (array, values, key = 'id') => ((map) => values.reduce((a,i) =>
a.push(map[i]) && a,[]))(array.reduce((a,i) => (a[i[key]] = i) && a, {}));
a = [2,3,1,4]
b = [{id: 1}, {id: 2}, {id: 3}, {id: 4}]
sortBy(b, a) // [{id: 2}, {id: 3}, {id: 1}, {id:` 4}]
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));