2016-11-17 89 views
0

我有一些形狀如下的對象。Javascript合併基於關鍵字的兩個對象

[{ 
    product: 'ABC', 
    productId: 'AB123', 
    batch: 'BA1', 
    price: '12' 
}, { 
    product: 'ABC', 
    productId: 'AB123', 
    batch: 'BA2', 
    price: '15' 
}, { 
    product: 'XYZ', 
    productId: 'AB124', 
    batch: 'XY1', 
    price: '124' 
}] 

我想如果密鑰對(product,和productId)被mathced,在下面的格式的對象合併爲一個單一的對象在數組中。

[{ 
    product: 'ABC', 
    productId: 'AB123', 
    batch: ['BA1', 'BA2'], 
    price: ['12', '15'] 
}, { 
    product: 'XYZ', 
    productId: 'AB124', 
    batch: 'XY1', 
    price: '124' 
}] 

我該如何在lodash或純javascript中做到這一點。

+2

分享你的研究可以幫助大家。告訴我們你試過了什麼,以及它爲什麼不符合你的需求。這表明你已經花時間去嘗試幫助自己,它使我們避免重申明顯的答案,最重要的是它可以幫助你得到更具體和相關的答案!另請參閱[如何問](http://stackoverflow.com/questions/how-to-ask) – Cerbrus

+0

預期的結果對象包含不同的結構。如果產品有多個條目,那麼您有批量和價格的數組,但如果沒有,則您只希望獲得單個值。 - 不應該產生的對象遵循共同的格式?即:始終爲批次/價格陣列,或者甚至可以是包含價格和批次對象的單個數組,以便知道哪個批次屬於哪個價格? – Nope

回答

3

該建議不會改變給定的數據。

它創建新的對象,首先只有單個數據,稍後如果應該組織更多的數據,它將使用數組batchprice

var data = [{ product: 'ABC', productId: 'AB123', batch: 'BA1', price: '12' }, { product: 'ABC', productId: 'AB123', batch: 'BA2', price: '15' }, { product: 'XYZ', productId: 'AB124', batch: 'XY1', price: '124'}], 
 
    merged = []; 
 

 
data.forEach(function (a) { 
 
    if (!this[a.productId]) { 
 
     this[a.productId] = { product: a.product, productId: a.productId, batch: a.batch, price: a.price }; 
 
     merged.push(this[a.productId]); 
 
     return; 
 
    } 
 
    if (!Array.isArray(this[a.productId].batch)) { 
 
     this[a.productId].batch = [this[a.productId].batch]; 
 
    } 
 
    if (!Array.isArray(this[a.productId].price)) { 
 
     this[a.productId].price = [this[a.productId].price]; 
 
    } 
 
    this[a.productId].batch.push(a.batch); 
 
    this[a.productId].price.push(a.price); 
 
}, Object.create(null)); 
 

 
console.log(merged);

+2

這次沒有你的班輪嗎? :D – fafl

+0

@fafl,來吧! –

+1

你太棒了! @NinaScholz –

0

是否必須是可讀?

var data = [{ 
    product: 'ABC', 
    productId: 'AB123', 
    batch: 'BA1', 
    price: '12' 
}, { 
    product: 'ABC', 
    productId: 'AB123', 
    batch: 'BA2', 
    price: '15' 
}, { 
    product: 'ABC', 
    productId: 'AB113', 
    batch: 'BA2', 
    price: 15 
}, { 
    product: 'XYZ', 
    productId: 'AB124', 
    batch: 'XY1', 
    price: '124' 
}] 
var unEs6 = function(x) { 
    if (x instanceof Map) { 
     var result = {} 
     for (let [key, value] of x.entries()) { 
      result[key] = unEs6(value); 
     } 
     return result; 
    } 
    else { 
     return x 
    } 
} 
JSON.stringify(unEs6(
    data 
     .map(
      row => (new Map().set(
       row.product, new Map().set(
        row.productId, new Map() 
         .set("batch", [row.batch]) 
         .set("price", [row.price]) 
        ) 
       ) 
      ) 
     ) 
     .reduce((a, b) => !a.has(b.keys().next().value) ? 
      new Map([...a, ...b]) : 
      !a.get(b.keys().next().value).has(b.get(b.keys().next().value).keys().next().value) ? 
       a.set(b.keys().next().value, new Map([ 
        ...a.get(b.keys().next().value), 
        ...b.get(b.keys().next().value) 
       ])) : 
       a.set(b.keys().next().value, a.get(b.keys().next().value).set(
        b.get(b.keys().next().value).keys().next().value, 
        new Map() 
         .set("batch", a.get(b.keys().next().value).get(b.get(b.keys().next().value).keys().next().value).get("batch") 
           .concat(b.get(b.keys().next().value).get(b.get(b.keys().next().value).keys().next().value).get("batch")) 
         ) 
         .set("price", a.get(b.keys().next().value).get(b.get(b.keys().next().value).keys().next().value).get("price") 
           .concat(b.get(b.keys().next().value).get(b.get(b.keys().next().value).keys().next().value).get("price")) 
         ) 
       )) 
     ) 
)) 
0

您可以在陣列中使用lodash的鏈_.transform()_.mergeWith()合併相似的對象:

function mergeSimilar(arr, arrayProps) { 
 
    // transform the array into a map object 
 
    return _(arr).transform(function(result, item) { 
 
    
 
    // create a temp id that includes the product and productId 
 
    var id = item.product + item.productId; 
 
    
 
    // merge the existing item with a new item 
 
    result[id] = _.mergeWith(result[id] || {}, item, function(objValue, srcValue, key) { 
 
     
 
     // if a value exists, and it's one of the request keys, concat them into a new array 
 
     if (!_.isUndefined(objValue) && _.includes(arrayProps, key)) { 
 
     return [].concat(objValue, srcValue); 
 
     } 
 
    }); 
 
    }, {}) 
 
    .values() // get the values from the map object 
 
    .value(); 
 
} 
 

 
var arr = [{ 
 
    product: 'ABC', 
 
    productId: 'AB123', 
 
    batch: 'BA1', 
 
    price: '12' 
 
}, { 
 
    product: 'ABC', 
 
    productId: 'AB123', 
 
    batch: 'BA2', 
 
    price: '15' 
 
}, { 
 
    product: 'XYZ', 
 
    productId: 'AB124', 
 
    batch: 'XY1', 
 
    price: '124' 
 
}]; 
 

 
var result = mergeSimilar(arr, ['batch', 'price']); 
 

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

1

您可以使用_.uniqWith遍歷集合,並得到擺脫重複。除此之外,uniqWith會授予您訪問對象的權限,以便您可以隨意篡改它們。

在這種情況下,當找到重複項時,我將其批次和價格添加到原始對象的數組中,以獲得所需的結果。

var arr = [{ 
 
    product: 'ABC', 
 
    productId: 'AB123', 
 
    batch: 'BA1', 
 
    price: '12' 
 
}, { 
 
    product: 'ABC', 
 
    productId: 'AB123', 
 
    batch: 'BA2', 
 
    price: '15' 
 
}, { 
 
    product: 'XYZ', 
 
    productId: 'AB124', 
 
    batch: 'XY1', 
 
    price: '124' 
 
}]; 
 

 
function addToArray(val1, val2) { 
 
    return _.isArray(val1) ? val1.concat(val2) : [val1].concat(val2); 
 
} 
 

 
function modifyObjs(a, b) { 
 
    b.batch = addToArray(b.batch, a.batch); 
 
    b.price = addToArray(b.price, a.price); 
 
    return true; 
 
} 
 

 
function predicateAndModifier(a, b) { 
 
    return a.product === b.product && a.productId === b.productId && modifyObjs(a, b); 
 
} 
 

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

0

Lodash 4.17.2

_.reduce(data, function(result, item) { 
    var added = _.find(result, { 
     product: item.product, 
     productId: item.productId 
    }); 
    if (_.isObject(added)) { 
     //!! better to merge with new object and add result to array again to avoid mutable 
     added = _.mergeWith(added, item, function(addedVal, itemVal, key) { 
      if (key === 'product' || key === 'productId') { 
       return addedVal; 
      } 
      return _.concat(addedVal, itemVal); 
     }); 
     return result; 
    } 
    return _.concat(result, item); 
}, []);