@kontr0l アプローチを他のアプローチよりも使用したい状況を実際に想像できますが、このアプローチは 2 次であることを理解する必要があるため、基本的にこのコードは単純なアプローチの抽象化であり、2 つの配列のすべての値を反復処理します。
二次式よりも優れたアプローチがあります。ここでは大きな O 表記は使用しませんが、ここに 2 つの主なアプローチを示します。どちらも素朴なアプローチよりも優れています。
- 配列の 1 つを繰り返し処理し、二分探索を使用して、並べ替えられた 2 番目の配列に存在するかどうかを確認します。
- set/hash/dictionary/名前を付けて値を入れます。
すでに述べたように、difference
メソッドのより柔軟なアナログを使用して標準メソッドを再実装する場合、最初のアプローチをオブジェクトに採用できますindexOf
。
2 番目のアプローチでは、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 は非負の整数です。より効率的なアルゴリズムを使用できます。
秘訣は、次のように 2 つのヘルパー配列を導入して 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();
}
そのため、作業中のデータの構造に依存すると、役立つ場合があります。