根据另一个ID数组对对象数组进行排序

ABC*_*ABC 3 javascript ramda.js

我有2个数组

a = [2,3,1,4]
b = [{id: 1}, {id: 2}, {id: 3}, {id: 4}]
Run Code Online (Sandbox Code Playgroud)

如何b根据排序a?我想要的输出是

c = [{id: 2}, {id: 3}, {id: 1}, {id: 4}]
Run Code Online (Sandbox Code Playgroud)

我更喜欢使用Ramda或常规JS。

arc*_*don 6

Ramda对于这些类型的问题确实很满意。

在数据大小较小的地方,我们可以使用简单的reduce函数和indexOf帮助器。

// 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 } ]
Run Code Online (Sandbox Code Playgroud)

这对于小型(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 } ]
Run Code Online (Sandbox Code Playgroud)

最后,这是另一种非常简洁的解决方案:

R.sortBy(R.pipe(R.prop('id'), R.indexOf(R.__, a)))(b);
// [ { id: 2 }, { id: 3 }, { id: 1 }, { id: 4 } ]
Run Code Online (Sandbox Code Playgroud)

我喜欢这样的方式:您可以使用行为组合功能,并使用Ramda将算法与算法所依据的数据分开。您最终将获得易于阅读且易于维护的代码。


Far*_*uja 6

使用 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));
Run Code Online (Sandbox Code Playgroud)


the*_*sti 5

您可以为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);
});
Run Code Online (Sandbox Code Playgroud)