web-dev-qa-db-ja.com

Underscore.JSを使用して2つのコレクションをマージする

2つのコレクションがある場合:

c1-[{a:1},{a:2},{a:3}]

そして

c2-[{a:1},{a:7},{a:8}]

c2を使用してc1からUnderscore.JSに一意のアイテムを追加する最も速い方法は何ですか?コレクション内の実数は2Kの場合はc1500の場合はc2になります。操作は頻繁に実行されるため、パフォーマンスが必要です。

更新1-数日だけUnderscore.JSを使用していますが、あるコレクションを別のコレクションに追加する方法が見つかりませんでした(自分でc2をフィルタリングできます)- Underscore.JSで些細なことですか?

27
user1514042

以下は:

  • c1とc2のすべての要素を含む新しい配列を作成します。 nion を参照してください。
  • そのミックスから、一意の要素のみを含む新しい配列を作成します。 niq を参照してください。

これは、すべてのオブジェクトにaプロパティがある場合にのみ機能することに注意してください。

_.uniq(_.union(c1, c2), false, function(item, key, a){ return item.a; });

この質問 で他のオプションを見つけることができます。

51
Matias

試してください:

__.uniq(_.union(c1, c2), false, _.property('a'))
_

詳細に:

  1. _.union(*arrays)

    渡された配列の和集合を計算します。

  2. _.property(key)(バージョン1.6.0以降)

    渡されたオブジェクトのキープロパティを返す関数を返します。

  3. _.uniq(array, [isSorted], [iteratee])

    _===_を使用してオブジェクトの等価性をテストし、重複のないバージョンの配列を生成します。配列がソートされていることが事前にわかっている場合、isSortedにtrueを渡すと、はるかに高速なアルゴリズムが実行されます。変換に基づいて一意のアイテムを計算する場合は、反復関数を渡します。

15
HaNdTriX

uniq()関数のドキュメントには、リストが並べ替えられている場合、はるかに高速に実行されることが記載されています。また、連鎖呼び出しを使用すると読みやすくなります。だからあなたができる:

__.chain(c1).union(c2).sortBy("a").uniq(true, function(item){ return item.a; }).value();
_

または、チェーンなしバージョン(11文字より短いが読みにくい)を好む場合:

__.uniq(_.sortBy(_.union(c1,c2),"a"),true, function(item){ return item.a; });
_

uniq()のドキュメントと例では、コールバック関数がどのように機能するかを明確にしません。 uniq()関数のアルゴリズムは、両方のリストのすべての要素でこの関数を呼び出します。この関数の結果が同じ場合、その要素は削除されます(重複していると仮定)。

union()は実際、配列で呼び出されたときに重複を防ぎます。この事実も使用できます。

__.map(_.union(_.pluck(c1,"a"),_.pluck(c2,"a")),function (item) {return {a:item};});
_

上記のように、最初にオブジェクトのリストを単純な配列(pluck())に変換し、union()を使用してそれらを結合し、最終的にmap()を使用してオブジェクトのリストを作成します。

リファレンス: niq()

6
AlexStack

両方のオブジェクトには膨大な数のプロパティがあり、このアルゴリズムは頻繁に実行されるため、ライブラリではなくコアJavaScriptを使用することをお勧めします。

//adds all new properties from the src to dst. If the property already exists, updates the number in dst. dst and src are objects
function extendNumberSet( dst, src ) {
    var allVals = [];
    for ( var i = 0; i < dst.length; i++ ) {
        allVals.Push(dst[i].a);
    }
    for ( var i = 0; i < src.length; i++ ) {
        if ( allVals.indexOf( src[i].a ) === -1 ) {
            dst.Push( src[i] );
        }
    }
}

テストするJSfiddle です。

1
AlexStack