我实际上可以想象我宁愿使用@kontr0l 方法而不是其他方法的情况,但是您必须了解这种方法是二次的,所以基本上这段代码是对幼稚方法的抽象——遍历两个数组中的所有值。
有比二次方更好的方法,我不会在这里使用任何大的 O 表示法,但这里有两种主要方法,两者都比天真的方法更好:
- 遍历其中一个数组并使用二进制搜索检查排序的第二个数组中是否存在。
- 将值放入 set/hash/dictionary/你命名它。
正如已经提到的,如果您difference
使用一些更灵活的方法类似物重新实现标准方法,则可以对对象采用第indexOf
一种方法。
使用第二种方法,我们可以碰壁,因为截至 2015 年 2 月,只有现代浏览器支持Sets。由于 javascript 中的哈希(嗯,对象),它们只能有字符串类型的键,所以任何作为键调用的对象首先应该通过toString
方法转换。所以,我们需要提供一些 => 对应。在大多数情况下的实践中,它非常简单,例如,对于您的特定示例,这种对应关系可以是String(obj.id)
.
有了这样的对应关系,我们还可以使用以下 lodas/undercore 方法:
var idsA = _.pluck(a, 'id');
var idsB = _.pluck(b, 'id');
// actually here we can stop in some cases, because
// quite often we need to identify object, but not the object itself -
// for instance to send some ids through remote API.
var intersect = _.intersection(idsA, idsB);
//to be 100% sure you get the idea, here we assume that object having equal ids are treated as equal, so does not really matter which of arrays we'll iterate:
var dictA = _.object(idsA, a); // now we can find a by id faster then with _.find
var intersectObj = intersect.map(function(id) {return dictA[id})
但是要承认稍微严格的限制——我们可以在我们的集合对象和自然数之间建立对应关系,我们可以建立更有效的算法,即我们所有的 id 都是非负整数——我们可以使用更有效的算法。
诀窍是通过以这种方式引入两个辅助数组来实现 set:
var naturalSet = function (arr) {
var sparse = [];
var dense = [];
var contains = function (i) {
var res = sparse[i] < dense.length && dense[sparse[i]] == i;
return res;
}
var add = function (v) {
if (!contains(v)) {
sparse[v] = dense.length;
dense.push(v);
}
}
arr.forEach(add);
return {
contains: contains,
toArray: function () {
return dense
},
_getDense: function () {
return dense
},
_getSparse: function () {
return sparse
}
}
}
然后我们可以引入带有映射到 naturalSet 的集合:
var set = function (arr, valueOf) {
var natSet = naturalSet(arr.map(valueOf));
return {
contains: function (item) {
return natSet.contains(valueOf(item))
},
toArray: function () {
var sparse = natSet._getSparse();
var res = natSet._getDense().map(function (i) {
return arr[sparse[i]];
});
return res;
}
}
}
最后,我们可以引入交集:
var intersection = function(arr1, arr2, valueOf) {
return set(arr2.filter(set(arr1, valueOf).contains), valueOf).toArray();
}
因此,依靠您正在处理的数据结构有时可以为您提供帮助。