2016-12-14 7 views
0

我有兩個對象數組。每個集合對象包含相似的屬性。我試圖將基於特定屬性的兩個集合一起壓縮。但是,有可能兩個數組中的某個特定對象可能不一定具有在另一個數組中具有匹配屬性值的對象。在這些情況下,我想要有空值。下面是想我做的一個例子:在Javascript中使用可能的空值壓縮兩個集合(可用lodash)

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

根據上市,下面應該工作的要求(使用Ramda,我相信使用應根據一個在lodash/fp具備的功能)

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。它將返回undefined而不是null,但如果它很重要,則可以映射它以更改它。

然而,根據什麼結果將被使用,如果在所有不需要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>

相關問題