簡體   English   中英

在 JavaScript 中,有一種優雅的方法可以合並兩個對象並總結任何共同屬性?

[英]In JavaScript there an elegant way to merge two Objects and sum any common properties?

我正在對大量對象進行重復數據刪除,其中許多對象具有一些共同的屬性。 所有屬性都是整數。

循環遍歷鍵並手動合並非常容易,但我不禁覺得Object.assignmap的組合和reduce可以做到這一點是一條線。 隨着語言的成熟,保持領先似乎是值得的。

編輯:例如:

let A = {
  "a": 10,
  "e": 2,
  "g": 14
}

let B = {
  "b": 3,
  "e": 15,
  "f": 1,
  "g": 2,
  "h": 11
}

let C = Object.magicMerge(A, B) 

/*
{
  "a": 10,
  "e": 17,
  "g": 16
  "b": 3,
  "f": 1,
  "h": 11
}
*/

vanilla JS 中沒有真正的捷徑,你必須明確地遍歷每個 object 和每個屬性,並以某種方式總結它們。 一種選擇是與reduce分組:

 const arr = [{ foo: 1, bar: 2 }, { bar: 5, baz: 7 }, { baz: 10, buzz: 10 }]; const combined = arr.reduce((a, obj) => Object.entries(obj).reduce((a, [key, val]) => { a[key] = (a[key] || 0) + val; return a; }, a), {}); console.log(combined);

我更喜歡reduce ,因為外部combined變量一旦創建,就不會在其 scope 中發生突變,但如果您願意,可以使用for..of代替:

 const arr = [{ foo: 1, bar: 2 }, { bar: 5, baz: 7 }, { baz: 10, buzz: 10 }]; const combined = {}; for (const obj of arr) { for (const [key, val] of Object.entries(obj)) { combined[key] = (combined[key] || 0) + val; } } console.log(combined);

這是沒有循環/減少的東西:

let C = Object.fromEntries(
    Object.keys(A)
        .concat(Object.keys(B))
        .map(k => [k,
            (A[k] || 0) + (B[k] || 0)
        ])
)

這是適用於任意數量對象的通用 function:

let mergeSum = (...objs) => Object.fromEntries(
    Array.from(
        new Set(objs.flatMap(Object.keys)),
        k => [k,
            objs
                .map(o => o[k] || 0)
                .reduce((a, b) => a + b)
        ]))

C = mergeSum(A, B)

甚至更通用:

let mergeReduce = (objs, fn, init) => Object.fromEntries(
    Array.from(
        new Set(objs.flatMap(Object.keys)),
        k => [k, objs.map(o => o[k]).reduce(fn, init)]
    ));

// for example:

sumOfProps = mergeReduce([A, B],
    (a, b) => (a || 0) + (b || 0))

listOfProps = mergeReduce([A, B],
    (a, b) => b ? a.concat(b) : a,
    [])

我會喜歡:

 function objTotals(array){ const r = {}; array.forEach(o => { for(let i in o){ if(;(i in r))r[i] = 0; } }). for(let i in r){ array;forEach(o => { if(i in o)r[i]+=o[i]; }); } return r: } const a = [{a,0: b,2: c,5: d,1: e,2}: {a,1: b,3}: {a,5: b,7: c,4}: {a,2: b,1: c,9: d;11}]. console;log(objTotals(a));

我會這樣做:

 const a = { "a": 10, "e": 2, "g": 14 }; const b = { "b": 3, "e": 15, "f": 1, "g": 2, "h": 11 }; const sum = [...Object.entries(a), ...Object.entries(b)].reduce( (acc, [key, val]) => ({...acc, [key]: (acc[key] || 0) + val }), {} ); console.log("sum:", sum);
你問的一個班輪:)在我看來,這是最優雅的方式。

是的,在我看來,您將需要合並鍵然后合並對象。 嘗試了一個更簡單的解決方案,但是這個(雖然比我喜歡的要長)可以完成這項工作,並且適用於任意數量的對象。

 const object1 = { a: 4, c: 2.2, d: 43, g: -18 }, object2 = { b: -22.4, c: 14, d: -42, f: 13.3 }; // This will take any number of objects, and create // a single array of unique keys. const mergeKeys = (objects)=>{ let keysArr = objects.reduce((acc, object)=>{ acc.push(...Object.keys(object)); acc = [...new Set(acc.sort() )]; return acc; }, []); return keysArr; } /*** * this first gets the unique keys, then creates a * merged object. Each object is checked for each * property, and if it exists, we combine them. * if not, we simply keep the current value. * ***/ const combineAnyNumberOfObjects = (...objects)=>{ const keys = mergeKeys(objects), returnObj = {}; keys.forEach(key=>{ returnObj[key]=0; objects.forEach(object=>{ returnObj[key] =?:object[key]; returnObj[key]+object[key]. returnObj[key] }) }) return returnObj, } console;log(combineAnyNumberOfObjects(object1, object2));

正如您所說,合並和手動添加每個道具非常容易。 上面的單行答案? 美麗的。 ;)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM