2013-06-22 5 views
47

プロパティ値の配列を使用してコレクションをフィルタリングしたいとします。 IDの配列が与えられた場合、IDが一致するオブジェクトを返します。 lodash/underscoreを使用するショートカット方法はありますか?lodash値の配列を使用したフィルタコレクション

var collections = [{ id: 1, name: 'xyz' }, 
        { id: 2, name: 'ds' }, 
        { id: 3, name: 'rtrt' }, 
        { id: 4, name: 'nhf' }, 
        { id: 5, name: 'qwe' }]; 
var ids = [1,3,4]; 

// This works, but any better way? 

var filtered = _.select(collections, function(c){  
    return ids.indexOf(c.id) != -1 
}); 
+0

しかし、Arrayプロトタイプの 'filter()'メソッドを直接扱うことができます。あなたはkeyByの終わりの引用を欠いています: – gustavohenke

答えて

58

あなたは、パターンのこの種をたくさん使用するつもりなら、あなたはしかし、それはあなたの元のコードよりもfundementally異なる何もしていないが、以下のようなミックスインを作成することができます。開発者にとってより使いやすいものにするだけです。

_.mixin({ 
    'findByValues': function(collection, property, values) { 
    return _.filter(collection, function(item) { 
     return _.contains(values, item[property]); 
    }); 
    } 
}); 

このように使用できます。

var collections = [ 
    {id: 1, name: 'xyz'}, 
    {id: 2, name: 'ds'}, 
    {id: 3, name: 'rtrt'}, 
    {id: 4, name: 'nhf'}, 
    {id: 5, name: 'qwe'} 
]; 

var filtered = _.findByValues(collections, "id", [1,3,4]); 

更新 - これ以上の答えは、古いものと不格好です。はるかに洗練されたソリューションにはanswer from Adam Boduchを使用してください。

_(collections) 
    .keyBy('id') // or .indexBy() if using lodash 3.x 
    .at(ids) 
    .value(); 
+0

私は修正するだろうが、私は単一の文字を追加することはできません;) –

6

私はjessegavin's答えを好むが、私は深い財産マッチングにlodash-deepを使用して、その上に拡大しました。

var posts = [{ term: { name: 'A', process: '123A' } }, 
      { term: { name: 'B', process: '123B' } }, 
      { term: { name: 'C', process: '123C' } }]; 

var result = _.filterByValues(posts, 'term.process', ['123A', '123C']); 
// results in objects A and C to be returned 

jsFiddle

_.mixin({ 
    'filterByValues': function(collection, key, values) { 
     return _.filter(collection, function(o) { 
      return _.contains(values, resolveKey(o, key)); 
     }); 
    } 
}); 

function resolveKey(obj, key) { 
    return (typeof key == 'function') ? key(obj) : _.deepGet(obj, key); 
} 

あなたはlodash-深く信頼していないか、あなたは自分の名前にドットを持つプロパティのサポートをしたい場合は、こちらより防御的かつ堅牢なバージョンです:

function resolveKey(obj, key) { 
    if (obj == null || key == null) { 
     return undefined; 
    } 
    var resolved = undefined; 
    if (typeof key == 'function') { 
     resolved = key(obj); 
    } else if (typeof key == 'string') { 
     resolved = obj[key]; 
     if (resolved == null && key.indexOf(".") != -1) { 
      resolved = _.deepGet(obj, key); 
     } 
    } 
    return resolved; 
} 
は、
+3

lodash 'get'はデフォルトで深いので、' _.get(object、 'a [0] .b.c') ; '。 @jessegavinが深いプロパティをサポートするために必要なことは、 'item.properties 'を' _.get(item、property) 'に変更することだけです。 [lodashドキュメント](https://lodash.com/docs#get)を参照してください。 – danbars

34

indexBy()at()を使用する簡潔なロダッシュ溶液。

_(collections) 
    .indexBy('id') 
    .at(ids) 
    .value(); 
+5

この解決策のこの忍耐はすばらしいです。そして、Lodash 4のユーザーは 'indexBy'を' keyBy'に置き換えるだけで機能し続けることができます。 –

+2

'collections'に' ids'でマッチするオブジェクトが含まれていない場合、それは未定義の要素を1つ持つ配列を返すようです。 '[undefined']。これは 'someArray.length'の私のテストに失敗したので、' .filter() ' ' _(collections).keyBy( '​​id')。at(ids).filter()。value(); 'を追加しました。 – steezeburger

12

我々はまた、私はこれらの答えの多くは古くなっているかLodashのマニュアルに記載されていない補助機能が含まれて気づいたこの

var collections = [{ id: 1, name: 'xyz' }, 
      { id: 2, name: 'ds' }, 
      { id: 3, name: 'rtrt' }, 
      { id: 4, name: 'nhf' }, 
      { id: 5, name: 'qwe' }]; 



     var filtered_ids = _.filter(collections, function(p){ 
      return _.includes([1,3,4], p.id); 
     }); 

     console.log(filtered_ids); 
0

のようにフィルタリングすることができます。受け入れられた回答には廃止された機能_.containsが含まれており、更新する必要があります。

ここに私のES6答えがあります。

Lodash v4.17.4

_.mixin({ 
    filterByValues: (c, k, v) => _.filter(
     c, o => _.indexOf(v, o[ k ]) !== -1 
    ) 
}); 

に基づいて、そのように呼び出さ:

_.filterByValues(
    [ 
     { 
      name: 'StackOverflow' 
     }, 
     { 
      name: 'ServerFault' 
     }, 
     { 
      name: 'AskDifferent' 
     } 
    ], 
    'name', 
    [ 'StackOverflow', 'ServerFault' ] 
); 

// => [ { name: 'StackOverflow' }, { name: 'ServerFault' } ] 
0

を私は非一意の値に基づいてフィルタリングしたかったので、これらの答えは、私のために動作しませんでした。 keyBygroupByに変更すると、それを取得できます。

_(collections) 
    .groupBy(attribute) 
    .pick(possibleValues) 
    .values() 
    .flatten() 
    .value(); 

私の最初の使用は、物事をドロップすることだったので、私はomitpickを切り替えます。

ありがとうございました。開始点はAdam Boduchです。

関連する問題