2016-12-14 7 views
0

私は2つのオブジェクトの配列を持っています。各コレクションオブジェクトには、同様のプロパティが含まれています。私は特定のプロパティに基づいて2つのコレクションを一緒に圧縮しようとしています。ただし、いずれかの配列内の特定のオブジェクトが、必ずしも他の配列内の一致するプロパティ値を持つオブジェクトを持つとは限りません。このような場合、null値が必要です。ここで私がやりたいものの例です:JavaScriptで可能なヌル値を持つ2つのコレクションを圧縮する(利用可能なロダッシュ)

var arr1 = [ 
    { id: '1', text: 'arr1 - one' }, 
    { id: '2', text: 'arr1 - two' }, 
    { id: '3', text: 'arr1 - three' } 
]; 

var arr2 = [ 
    { id: '1', text: 'arr2 - one' }, 
    { id: '2', text: 'arr2 - two' }, 
    { id: '4', text: 'arr2 - four' } 
]; 

結果:

{ 
    '1': [ 
    { id: '1', text: 'arr1 - one' }, 
    { id: '1', text: 'arr2 - one' } 
    ] 

    '2': [ 
    { id: '2', text: 'arr1 - two' }, 
    { id: '2', text: 'arr2 - two' } 
    ], 

    '3': [ 
    { id: '3', text: 'arr1 - three' }, 
    null 
    ], 

    '4': [ 
    null, 
    { id: '4', text: 'arr2 - four' } 
    ] 

そのライブラリを使用しての答えは歓迎されているので、私はすでに、プロジェクトにlodash 4依存性を持っています。

+0

の重要な結果の順序ですか? – Ben

+0

はい、いいえ。これがキーで使用される最終的な場所はソートされる必要があります。しかし、それらがランダムであれば、Object.keys()を使用して結果をソートし、ソートされた配列を使用して正しい順序で情報を取得することで、簡単に回避できます。 – jhummel

+0

最小ブラウザ/ノード? – Ben

答えて

1
_.chain(arr1) 
    .concat(arr2) 
    .map('id') 
    .uniq() //get all possible ids without dublicates 
    .reduce(function (result, id) { 
     result[id] = _.map([arr1, arr2], function (arr) { //find object in each array by id 
      return _.find(arr, {id: id}) || null;  //if not found set null 
     }); 
     return result; 
    }, {}) 
    .value(); 
0

記載されている要件によると、以下の(私が使用する機能がlodash/fpの1に従っているはずと信じて、Ramdaを使用して)動作するはずですが

var arr1 = [ 
    { id: '3', text: 'arr1 - one' }, 
    { id: '2', text: 'arr1 - two' }, 
    { id: '1', text: 'arr1 - three' } 
]; 

var arr2 = [ 
    { id: '4', text: 'arr2 - one' }, 
    { id: '2', text: 'arr2 - two' }, 
    { id: '1', text: 'arr2 - four' } 
]; 

var idList = R.pipe(
    R.concat, 
    R.map(R.prop('id')), 
    R.uniq, 
    R.sortBy(R.identity) 
)(arr1, arr2); 

var findById = (id) => R.find(R.propEq('id', id)); 

return R.map(
    (id) => [ 
    findById(id)(arr1), 
    findById(id)(arr2) 
    ] 
)(idList); 

ここlinkです。 nullの代わりにundefinedが返されますが、重要であればそれをマップして変更することができます。

null値が全く必要とされていない場合は、結果が使用されるものに応じて、groupWith

return R.pipe(
    R.concat, 
    R.sortBy(R.prop('id')), 
    R.groupWith(R.eqProps('id')) 
)(arr1, arr2); 

linkとの簡単なバージョンがあります。

1

function zip(a, b, propName) { 
 
    const result = new Map(); 
 
    a.forEach(i=> result.set(i[propName], [i, null])); 
 
    b.forEach(i=> { 
 
     let item = result.get(i[propName]); 
 
     item ? (item[1] = i) : (result.set(i[propName], [null, i])); 
 
    }); 
 
    return result; 
 
} 
 

 
var arr1 = [ 
 
    { id: '1', text: 'arr1 - one' }, 
 
    { id: '2', text: 'arr1 - two' }, 
 
    { id: '3', text: 'arr1 - three' } 
 
]; 
 

 
var arr2 = [ 
 
    { id: '1', text: 'arr2 - one' }, 
 
    { id: '2', text: 'arr2 - two' }, 
 
    { id: '4', text: 'arr2 - four' } 
 
]; 
 
console.log(JSON.stringify([...zip(arr1, arr2, 'id')], null, ' '));

0

このビット困難なことは、それらがグループ化された順序と一致する各グループにヌル値が必要なことです。あなたはヌルを必要としなかった場合たとえば、この問題はのように簡単になります:グループに、

_.groupBy(arr1.concat(arr2), 'id') 

ただしとヌルを維持し、あなたはgroupByはプリベーク来ないことを冗長性のビットを追加する必要がありますと。次のような独自のグループ関数を記述することができます

function group(...arrs) { // extensible to any number of arrays 
 
    // construct an object with empty arrays for all available ids 
 
    let rslt = _.chain(arrs) 
 
       .flatten() 
 
       .map(el => el.id) 
 
       .uniq() 
 
       .reduce((memo, el) => { 
 
       memo[el] = [] 
 
       return memo 
 
       }, {}) 
 
       .value() 
 
    // as we iterate, first set resulting object's bucket value to null 
 
    // Replace this value if it exists while iterating 
 
    _.each(arrs, (arr, i) => { 
 
    _.each(rslt, v => { 
 
     v.push(null) 
 
    }) 
 
    _.each(arr, el => { 
 
     rslt[el.id][i] = el 
 
    }) 
 
    }) 
 
    return rslt 
 
} 
 

 
var arr1 = [{ 
 
    id: '3', 
 
    text: 'arr1 - one' 
 
}, { 
 
    id: '2', 
 
    text: 'arr1 - two' 
 
}, { 
 
    id: '1', 
 
    text: 'arr1 - three' 
 
}]; 
 

 
var arr2 = [{ 
 
    id: '4', 
 
    text: 'arr2 - one' 
 
}, { 
 
    id: '2', 
 
    text: 'arr2 - two' 
 
}, { 
 
    id: '1', 
 
    text: 'arr2 - four' 
 
}]; 
 

 
console.log(group(arr1, arr2))
<script src="https://cdn.jsdelivr.net/lodash/4.17.2/lodash.min.js"></script>

^は、結果のログを確認するためにスニペットを実行します。

0

あなたは_.groupBy()_.mapValues()でこれを行うことができます。

const zipByKey = (arr1, arr2, zipKey) => { 
 
    // group arr2 by the zipKey 
 
    const group2 = _.groupBy(arr2, zipKey); 
 
    
 
    return _(arr1) 
 
    // group arr1 by the zipKey 
 
    .groupBy(zipKey) 
 
    // merge group1 with group2, if object is not in group1 substitute with null 
 
    .mergeWith(group2, (objValue, srcValue) => (objValue || [null]).concat(srcValue)) 
 
    // map the groups, if object is not in group2 substitute with null 
 
    .mapValues((group, zipKey) => group2[zipKey] ? group : group.concat(null)) 
 
    .value(); 
 
} 
 

 
const arr1 = [{"id":"1","text":"arr1 - one"},{"id":"2","text":"arr1 - two"},{"id":"3","text":"arr1 - three"}], arr2 = [{"id":"1","text":"arr2 - one"},{"id":"2","text":"arr2 - two"},{"id":"4","text":"arr2 - four"}]; 
 

 
const result = zipByKey(arr1, arr2, 'id'); 
 

 
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>

関連する問題