web-dev-qa-db-ja.com

JavaScript用アンダースコアを使用した重複オブジェクトの削除

私はこの種の配列を持っています:

var foo = [ { "a" : "1" }, { "b" : "2" }, { "a" : "1" } ];

私はそれをフィルタリングしたい:

var bar = [ { "a" : "1" }, { "b" : "2" }];

_.uniqを使用してみましたが、{ "a" : "1" }がそれ自体と等しくないため、機能しません。アンダースコアuniqにオーバーライドされたequals関数を提供する方法はありますか?

122
plus-

。uniq /。uniqueはコールバックを受け入れます

var list = [{a:1,b:5},{a:1,c:5},{a:2},{a:3},{a:4},{a:3},{a:2}];

var uniqueList = _.uniq(list, function(item, key, a) { 
    return item.a;
});

// uniqueList = [Object {a=1, b=5}, Object {a=2}, Object {a=3}, Object {a=4}]

ノート:

  1. 比較に使用されるコールバックの戻り値
  2. 一意として使用される一意の戻り値を持つ最初の比較オブジェクト
  3. nderscorejs.org はコールバックを使用しないことを示します
  4. lodash.com は使用法を示します

別の例: コールバックを使用して自動車メーカー、リストから色を抽出

230
Shanimal

IDに基づいて重複を削除する場合は、次のようなことができます。

var res = [
  {id: 1, content: 'heeey'},
  {id: 2, content: 'woah'}, 
  {id: 1, content:'foo'},
  {id: 1, content: 'heeey'},
];
var uniques = _.map(_.groupBy(res,function(doc){
  return doc.id;
}),function(grouped){
  return grouped[0];
});

//uniques
//[{id: 1, content: 'heeey'},{id: 2, content: 'woah'}]
38
Petter

Shipluの回答の実装。

var foo = [ { "a" : "1" }, { "b" : "2" }, { "a" : "1" } ];

var x = _.uniq( _.collect( foo, function( x ){
    return JSON.stringify( x );
}));

console.log( x ); // returns [ { "a" : "1" }, { "b" : "2" } ]
17
Larry Battle

私が属性IDを持っているとき、これはアンダースコアでの私の好ましい方法です:

var x = [{i:2}, {i:2, x:42}, {i:4}, {i:3}];
_.chain(x).indexBy("i").values().value();
// > [{i:2, x:42}, {i:4}, {i:3}]
15
tuxbear

nderscore unique libを使用すると、以下が機能します。_idに基づいてリストを一意にし、_idの文字列値を返します。

var uniqueEntities = _.uniq(entities, function (item, key, a) {
                                    return item._id.toString();
                                });
11
Aqib Mumtaz

簡単な解決策は、ディープオブジェクト比較を使用して重複をチェックします(非効率的でハッキングされるJSONへの変換に頼ることはありません)

var newArr = _.filter(oldArr, function (element, index) {
    // tests if the element has a duplicate in the rest of the array
    for(index += 1; index < oldArr.length; index += 1) {
        if (_.isEqual(element, oldArr[index])) {
            return false;
        }
    }
    return true;
});

配列の後半に重複がある場合は、すべての要素を除外します-最後の重複した要素が保持されるようにします。

重複のテストでは、_.isEqualを使用して、2つのオブジェクト間で最適化された詳細な比較を実行します。詳細については、 アンダースコアisEqualドキュメント を参照してください。

編集:_.filterを使用するように更新され、よりクリーンなアプローチになりました

10
Joshua Bambrick

Lodash 4.6.1のドキュメントには、オブジェクトキーの等価性の例としてこれがあります。

_.uniqWith(objects, _.isEqual);

https://lodash.com/docs#uniqWith

8
Ryan Quinn

イテレータ関数を試す

たとえば、最初の要素を返すことができます

x = [['a',1],['b',2],['a',1]]

_.uniq(x,false,function(i){  

   return i[0]   //'a','b'

})

=> [['' a '、1]、[' b '、2]]

7
IvanM

with nderscore i iteratee関数でString()を使用しなければならなかった

function isUniq(item) {
    return String(item.user);
}
var myUniqArray = _.uniq(myArray, isUniq);
3
dam1

ここに私の解決策があります(coffeescript):

_.mixin
  deepUniq: (coll) ->
    result = []
    remove_first_el_duplicates = (coll2) ->

      rest = _.rest(coll2)
      first = _.first(coll2)
      result.Push first
      equalsFirst = (el) -> _.isEqual(el,first)

      newColl = _.reject rest, equalsFirst

      unless _.isEmpty newColl
        remove_first_el_duplicates newColl

    remove_first_el_duplicates(coll)
    result

例:

_.deepUniq([ {a:1,b:12}, [ 2, 1, 2, 1 ], [ 1, 2, 1, 2 ],[ 2, 1, 2, 1 ], {a:1,b:12} ]) 
//=> [ { a: 1, b: 12 }, [ 2, 1, 2, 1 ], [ 1, 2, 1, 2 ] ]
3
szymanowski
var foo = [ { "a" : "1" }, { "b" : "2" }, { "a" : "1" } ];
var bar = _.map(_.groupBy(foo, function (f) { 
        return JSON.stringify(f); 
    }), function (gr) { 
        return gr[0]; 
    }
);

これを分解しましょう。まず、文字列化された値で配列項目をグループ化します

var grouped = _.groupBy(foo, function (f) { 
    return JSON.stringify(f); 
});

groupedは次のようになります。

{
    '{ "a" : "1" }' = [ { "a" : "1" } { "a" : "1" } ],
    '{ "b" : "2" }' = [ { "b" : "2" } ]
}

次に、各グループから最初の要素を取得します

var bar = _.map(grouped, function(gr)
    return gr[0]; 
});

barは次のようになります:[ { "a" : "1" }, { "b" : "2" } ]

すべてまとめてください:

var foo = [ { "a" : "1" }, { "b" : "2" }, { "a" : "1" } ];
var bar = _.map(_.groupBy(foo, function (f) { 
        return JSON.stringify(f); 
    }), function (gr) { 
        return gr[0]; 
    }
);
0
Kelly Bigley

私はこの単純な解決策を簡単な記述方法で解決したかったのですが、計算コストを少し苦しめました...しかし、最小の変数定義を備えた些細な解決策ではありませんか?

function uniq(ArrayObjects){
  var out = []
  ArrayObjects.map(obj => {
    if(_.every(out, outobj => !_.isEqual(obj, outobj))) out.Push(obj)
  })
  return out
}
0
Junji Shimagaki