簡體   English   中英

如何在Javascript中合並對象數組?

[英]How do I merge an array of objects in Javascript?

例:

var array1 = [ {'key':1, 'property1': 'x'}, {'key':2, 'property1': 'y'} ]
var array2 = [ {'key':2, 'property2': 'a'}, {'key':1, 'property2': 'b'} ]

我想合並(array1,array2)給我:

[
    {'key':1, 'property1': 'x', 'property2' : 'b'},
    {'key':2, 'property1': 'y', 'property2' : 'a'}
]

是否有捷徑可尋?

編輯:有幾個人已經回答,沒有仔細看我的問題,請注意我想匹配每個數組中的類似對象,並將他們的屬性組合到我的最終數組。 鍵是唯一的,每個陣列中最多只有一個具有特定鍵的對象。

我寫了一個 快速 不那么快的解決方案。 您可能要考慮的一個問題是,第二個數組中的對象的屬性是否應覆蓋與其進行比較的第二個對象中的相同屬性(如果存在)。

解決方案1

該解決方案具有復雜度O(n²) 解決方案2更快; 這個解決方案僅適用於那些不想快速成為刺蝟Sanic的人

JavaScript的

var mergeByKey = function (arr1, arr2, key) {
// key is the key that the function merges based on
    arr1.forEach(function (d, i) {
        var prop = d[key];
        // since keys are unique, compare based on this key's value
        arr2.forEach(function (f) {
            if (prop == f[key]) {    // if true, the objects share keys
                for (var x in f) {   // loop through each key in the 2nd object
                    if (!(x in d))   // if the key is not in the 1st object
                        arr1[i][x] = f[x];    // add it to the first object
                // this is the part you might want to change for matching properties
                // which object overrides the other?
                }
            }
        })
    })
    return arr1;
}

測試用例

var arr = [ {'key':1, 'property1': 'x'},
            {'key':2, 'property1': 'y'} ],
    arr2= [ {'key':2, 'property2': 'a'},
            {'key':1, 'property2': 'b'} ];

console.log(mergeByKey(arr, arr2, "key"));

結果

/* returns:
    Object
    key: 1
    property1: "x"
    property2: "b"
    __proto__: Object
and 
    Object
    key: 2
    property1: "y"
    property2: "a"
    __proto__: Object
*/

小提琴

解決方案2

正如Vivin Paliath在下面的評論中指出的那樣,我的第一個解決方案是O(n²)復雜度(讀:壞)。 他的答案非常好,並提供了復雜度為O(m + n)的解決方案,其中m是第一個數組的大小,第二個數組是n 換句話說,復雜度為O(2n)

但是,他的解決方案並未解決對象內的對象。 為了解決這個問題,我使用了遞歸讀取:魔鬼,就像O(n²)

JavaScript的

var mergeByKey = function (arr1, arr2, key) {
    var holder = [],
        storedKeys = {},
        i = 0; j = 0; l1 = arr1.length, l2 = arr2.length;

    var merge = function (obj, ref) {
        for (var x in obj) {
            if (!(x in ref || x instanceof Object)) {
                ref[x] = obj[x];
            } else {
                merge(obj[x], ref[x]);
            }
        }
        storedKeys[obj.key] = ref;
    }
    for (; i < l1; i++) {
        merge(arr1[i], storedKeys[arr1[i].key] || {});
    }
    for (; j < l2; j++) {
        merge(arr2[j], storedKeys[arr2[j].key] || {});
    }

    delete storedKeys[undefined];

    for (var obj in storedKeys)
        holder.push(storedKeys[obj]);

    return holder;
}

測試用例

var arr1 = [
    {
        "key" : 1,
        "prop1" : "x",
        "test" : {
            "one": 1,
            "test2": {
                "maybe" : false,
                "test3": { "nothing" : true }
            }
        }
    },
    {
        "key" : 2,
        "prop1": "y",
        "test" : { "one": 1 }
    }],
    arr2 = [
        {
            "key" : 1,
            "prop2" : "y",
            "test" : { "two" : 2 }
        },
        {
            "key" : 2,
            "prop2" : "z",
            "test" : { "two": 2 }
        }];
console.log(mergeByKey(arr1, arr2, "key"));

結果

/*
Object
    key: 1
    prop1: "x"
    prop2: "y"
    test: Object
        one: 1
        test2: Object
            maybe: false
            test3: Object
                nothing: true
                __proto__: Object
            __proto__: Object
        two: 2
        __proto__: Object
    __proto__: Object
Object
    key: 2
    prop1: "y"
    prop2: "z"
    test: Object
        one: 1
        two: 2
        __proto__: Object
    __proto__: Object
*/

這會正確合並對象以及所有子對象。 此解決方案假定具有匹配keys對象具有相同的層次結構。 它也不處理兩個數組的合並。

小提琴

你可以這樣做:

function merge(array1, array2) {
    var keyedResult = {};

    function _merge(element) {
        if(!keyedResult[element.key]) {
            keyedResult[element.key] = {};
        }

        var entry = keyedResult[element.key];
        for(var property in element) if(element.hasOwnProperty(property)) {
            if(property !== "key") {
                entry[property] = element[property];
            }                
        }

        entry["key"] = element.key;
    }

    array1.forEach(_merge);
    array2.forEach(_merge);

    var result = [];

    for(var key in keyedResult) if(keyedResult.hasOwnProperty(key)) {
        result.push(keyedResult[key]);
    }

    return result.sort(function(a, b) {
        return a.key - b.key;
    });
}

如果您不關心訂單,可以取消排序。 另一種選擇是使用數組而不是我使用的地圖( keyedResult ),如果你有數字鍵並且不關心數組是稀疏的(即,如果鍵是非連續數字)。 這里的鍵也是數組的索引。

該解決方案也在O(n)運行。

小提琴

最好使用現有的基礎設施,如_.groupBy_.groupBy_.extend來處理這樣的情況,而不是重新發明輪子。

function merge(array1, array2) {

  // merge the arrays
  // [ {'key':1, 'property1': 'x'}, {'key':2, 'property1': 'y'}, {'key':2, 'property2': 'a'}, {'key':1, 'property2': 'b'} ]
  var merged_array = array1.concat(array2);

  // Use _.groupBy to create an object indexed by key of relevant array entries
  // {1: [{ }, { }], 2: [{ }, { }]}
  var keyed_objects = _.groupBy(merged_array, 'key');

  // for each entry in keyed_objects, merge objects
  return Object.keys(keyed_objects).map(function(key) {
    return _.extend.apply({}, keyed_objects[key]);
  });

}

這里的想法是使用_.extend.apply將在特定鍵下分組的對象數組作為參數傳遞給_.extend ,這將把它們全部合並到一個對象中。

暫無
暫無

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

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