![](/img/trans.png)
[英]In JavaScript there an elegant way to merge two Objects and sum any common properties?
[英]Merge two javascript objects adding values of common properties
我有兩個或多個 javascript 對象。 我想合並它們添加公共屬性的值,然后按值的降序對它們進行排序。
例如
var a = {en : 5,fr: 3,in: 9}
var b = {en: 8,fr: 21,br: 8}
var c = merge(a,b)
c
應該是這樣的:
c = {
fr: 24,
en: 13,
in:9,
br:8
}
即合並兩個對象,添加公共鍵的值,然后對鍵進行排序。
這是我嘗試過的:
var a = {en : 5,fr: 3,in: 9}
var b = {en: 8,fr: 21,br: 8}
c = {}
// copy common values and all values of a to c
for(var k in a){
if(typeof b[k] != 'undefined'){
c[k] = a[k] + b[k]
}
else{ c[k] = a[k]}
}
// copy remaining values of b (which were not common)
for(var k in b){
if(typeof c[k]== 'undefined'){
c[k] = b[k]
}
}
// Create a object array for sorting
var arr = [];
for(var k in c){
arr.push({lang:k,count:c[k]})
}
// Sort object array
arr.sort(function(a, b) {
return b.count - a.count;
})
但我不認為它好。 這么多循環:(如果有人能提供一個不那么混亂和好的代碼,那就太好了。
在 ES2015+ 中,對象屬性是有序的(首先是數字鍵的升序,然后是非數字鍵的插入順序)。 如果您使用指定迭代順序的方法之一(例如Object.getOwnPropertyNames
),則規范可以保證這一點。
在 ES2020+ 中,以前未指定枚舉順序的方法現在已指定(盡管環境已經遵循它多年了)。
但是您必須確保沒有任何屬性是數字的(否則,無論插入順序如何,它們都會先出現在非數字屬性之前)。
使用reduce
迭代每個對象並在累加器上創建或添加相同的屬性。 然后, sort
對象的條目進行sort
,並使用Object.fromEntries
將其轉換為具有排序屬性的對象。 不需要 jQuery:
var a = {en : 5,fr: 3,in: 9} var b = {en: 8,fr: 21,br: 8} console.log(merge(a, b)); function merge(...objects) { const merged = objects.reduce((a, obj) => { Object.entries(obj).forEach(([key, val]) => { a[key] = (a[key] || 0) + val; }); return a; }, {}); return Object.fromEntries( Object.entries(merged).sort( (a, b) => b[1] - a[1] ) ); }
無法對對象的屬性進行排序,但是您可以對數組進行排序:
var merged = $.extend({}, a);
for (var prop in b) {
if (merged[prop]) merged[prop] += b[prop];
else merged[prop] = b[prop];
}
// Returning merged at this point will give you a merged object with properties summed, but not ordered.
var properties = [];
for (var prop in merged) {
properties.push({
name: prop,
value: merged[prop]
});
}
return properties.sort(function(nvp1, nvp2) {
return nvp1.value - nvp2.value;
});
編輯 - 我修改了腳本,如果屬性屬於相同類型,則合並屬性:數字相加,字符串連接,對象遞歸合並。 我沒有包括排序,因為(引用這個答案Sorting JavaScript Object by property value )
JavaScript 對象根據定義是無序的(參見 ECMAScript 語言規范,第 8.6 節)。 語言規范甚至不能保證,如果您連續兩次迭代對象的屬性,它們第二次將以相同的順序出現。
如果您需要訂購東西,請使用數組和 Array.prototype.sort 方法。
function is_object(mixed_var) {
if (Object.prototype.toString.call(mixed_var) === '[object Array]') {
return false;
}
return mixed_var !== null && typeof mixed_var == 'object';
}
function merge(a, b) {
var cache = {};
cache = unpackObject(a, cache);
cache = unpackObject(b, cache);
return cache;
}
function unpackObject(a, cache) {
for (prop in a) {
if (a.hasOwnProperty(prop)) {
if (cache[prop] === undefined) {
cache[prop] = a[prop];
} else {
if (typeof cache[prop] === typeof a[prop]) {
if (is_object(a[prop])) {
cache[prop] = merge(cache[prop], a[prop]);
} else {
cache[prop] += a[prop];
}
}
}
}
}
return cache;
}
var a = {
en: 5,
fr: 3,
in : 9,
lang: "js",
object: {nestedProp: 6}
}
var b = {
en: 8,
fr: 21,
br: 8,
lang: "en",
object: {nestedProp: 1, unique: "myne"}
}
var c = merge(a, b);
這是我的嘗試,它對嵌套對象是遞歸的 - https://gist.github.com/greenafrican/19bbed3d8baceb0a15fd
// Requires jQuery
// Merge nested objects and if the properties are numbers then add them together, else
// fallback to jQuery.extend() result
function mergeObjectsAdd(firstObject, secondObject) {
var result = $.extend(true, {}, firstObject, secondObject);
for (var k in result) {
if ("object" === typeof result[k]) {
firstObject[k] = firstObject[k] || {};
secondObject[k] = secondObject[k] || {};
result[k] = mergeObjectsAdd(firstObject[k], secondObject[k]);
} else {
firstObject[k] = firstObject[k] || 0;
secondObject[k] = secondObject[k] || 0;
result[k] = ("number" === typeof firstObject[k] && "number" === typeof secondObject[k]) ? (firstObject[k] + secondObject[k]) : result[k];
}
}
return result;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.