最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

jquery - Merge two javascript objects adding values of common properties - Stack Overflow

programmeradmin3浏览0评论

I have two or more javascript objects. I want to merge them adding values of mon properties and then sort them in descending order of values.

e.g.

var a = {en : 5,fr: 3,in: 9}
var b = {en: 8,fr: 21,br: 8}

var c = merge(a,b)

c should then be like this:

c = {
fr: 24,
en: 13,
in:9,
br:8
} 

i.e. both objects are merge, values of mon keys are added and then keys are sorted.

Here's what I've tried:

var a = {en : 5,fr: 3,in: 9}
var b = {en: 8,fr: 21,br: 8}
c = {}

// copy mon 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 mon)
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;
})

but I dont think its good. So many loops :( It would be nice if someone can provide a less messy and good code.

I have two or more javascript objects. I want to merge them adding values of mon properties and then sort them in descending order of values.

e.g.

var a = {en : 5,fr: 3,in: 9}
var b = {en: 8,fr: 21,br: 8}

var c = merge(a,b)

c should then be like this:

c = {
fr: 24,
en: 13,
in:9,
br:8
} 

i.e. both objects are merge, values of mon keys are added and then keys are sorted.

Here's what I've tried:

var a = {en : 5,fr: 3,in: 9}
var b = {en: 8,fr: 21,br: 8}
c = {}

// copy mon 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 mon)
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;
})

but I dont think its good. So many loops :( It would be nice if someone can provide a less messy and good code.

Share Improve this question edited Feb 7, 2012 at 11:44 Jashwant asked Feb 7, 2012 at 10:54 JashwantJashwant 29k16 gold badges75 silver badges108 bronze badges 7
  • see this link api.jquery./jQuery.merge – mgraph Commented Feb 7, 2012 at 10:57
  • @Dogbert So far I am here, pastebin./VQehhcri – Jashwant Commented Feb 7, 2012 at 11:02
  • Plain objects are not sorted. You'll need to go for an array to achieve sorting. – Chris Morgan Commented Feb 7, 2012 at 11:25
  • None of the answers below is working but I have found a way, but I dont think its good. Please look into that and optimise the code. Here's the pastebin. pastebin./nEKB7zAc – Jashwant Commented Feb 7, 2012 at 11:35
  • 1 @Jashwant your code for sorting is ok, as long as the porpoerties are numbers – Nicola Peluchetti Commented Feb 7, 2012 at 11:59
 |  Show 2 more ments

4 Answers 4

Reset to default 3

In ES2015+, object properties are ordered (first by ascending numeric keys, then by insertion order for non-numeric keys). This is guaranteed by the specification if you use one of the methods for which iteration order is specified (like Object.getOwnPropertyNames).

In ES2020+, the methods for which enumeration order used to be unspecified are now specified (though environments have been following it for ages anyway).

But you have to be sure that none of the properties are numeric (otherwise, they'll e first, before non-numeric properties, no matter the insertion order).

Use reduce to iterate over each object and create or add to the same property on the accumulator. Then, sort the object's entries, and use Object.fromEntries to transform it into an object with sorted properties. No need for 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]
    )
  );
}

It is not possible to sort the properties of an object, you can however sort an array:

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;
});

EDIT - i modified the script, this merges the properties if they are of the same type: numbers are summed, strings are concatenated and objects are recursively merged. I didn't include sorting because (quoting this answer Sorting JavaScript Object by property value)

JavaScript objects are unordered by definition (see the ECMAScript Language Specification, section 8.6). The language specification doesn't even guarantee that, if you iterate over the properties of an object twice in succession, they'll e out in the same order the second time.

If you need things to be ordered, use an array and the Array.prototype.sort method.

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);

fiddle here http://jsfiddle/vyFN8/1/

Here is my attempt, which is recursive for nested objects - https://gist.github./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;
}
发布评论

评论列表(0)

  1. 暂无评论