javascript - 基于每个关键属性的连接合并/扩展javascript对象数组

标签 javascript arrays object merge

我想通过首先加入 id 属性来合并以下对象数组

var arr1 = [{
    id: 1,
    name: 'fred',
    title: 'boss'
},{
    id: 2,
    name: 'jim',
    title: 'nobody'
},{
    id: 3,
    name: 'bob',
    title: 'dancer'
}];

var arr2 = [{
    id: 1,
    wage: '300',
    rate: 'day'
},{
    id: 2,
    wage: '10',
    rate: 'hour'
},{
    id: 3,
    wage: '500',
    rate: 'week'
}];

那么结果就是

[{
    id: 1,
    name: 'fred',
    title: 'boss',
    wage: '300',
    rate: 'day'
},{
    id: 2,
    name: 'jim',
    title: 'nobody',
    wage: '10',
    rate: 'hour'
},{
    id: 3,
    name: 'bob',
    title: 'dancer',
    wage: '500',
    rate: 'week'
}]

我想避免使用 js 框架(如果可能的话),尽管 ExtJs 已经是项目的一部分。 目前我有一个带有内循环的循环,如果键匹配,它会复制属性并跳出内循环以开始下一个外循环。

有更好的建议吗?

最佳答案

像这样?

var combined = [];
function findSecond(id,second){
    for (var i=0;i<second.length;i++){
        if(second[i].id === id){
            return second[i];
        }
    }
    return null
}

while (el = arr1.pop()){
    var getSec = findSecond(el.id,arr2);
    if (getSec){
        for (var l in getSec){
            if (!(l in el)) {
                el[l] = getSec[l];
            }
        }
        combined.push(el);
    }
}

如果数组的长度相同,并且 id 相等,则可以进行更简单的合并:

function merge(a1,a2) {
    var i = -1;
    while ((i = i+1)<a1.length)  {
     for (var l in a2[i]) {
            if (!(l in a1[i] )) {
                a1[i][l] = a2[i][l];
            }
     }
    }
   return a1; 
}

这是一个 working example

[编辑 2016 年 7 月 30 日] 添加了一个使用更多功能方法的片段,并且基于@djangos 评论,一个额外的方法来组合两个数组。 p>

(function() {
    var alert = function(str) {document.querySelector('#result').textContent += str + '\n';};
    var arrays = getArrays();
  
    alert('Combine on id (shared id\'s):')
    alert(JSON.stringify(combineById(arrays.arr1, arrays.arr2), null, ' '));
  
    alert('\nCombine on id (all id\'s):')
    alert(JSON.stringify(combineBothById(arrays.arr1, arrays.arr2), null, ' '));
  
    // for combineBothById the parameter order isn't relevant
    alert('\nCombine on id (all id\'s, demo parameter order not relevant):')
    alert(JSON.stringify(combineBothById(arrays.arr2, arrays.arr1), null, ' '));
  
    // combine first array with second on common id's
    function combineById(arr1, arr2) {
      return arr1.map(
          function (el) {
                var findInB = this.filter(function (x) {return x.id === el.id;});
                if (findInB.length) {
                    var current = findInB[0];
                    for (var l in current) {
                        if (!el[l]) {el[l] = current[l];}
                    }
                }
                return el;
          }, arr2);
    }

    // combine first array with second on all id's
    function combineBothById(arr1, arr2) {
        var combined = arr1.map(
            function (el) {
                var findInB = this.filter(function (x) {return x.id === el.id;});
                if (findInB.length) {
                    var current = findInB[0];
                    for (var l in current) {
                        if (!el[l]) {el[l] = current[l];}
                    }
                }
                return el;
            }, arr2);
        combined = combined.concat(arr2.filter(
            function (el) {
                return !this.filter(function (x) {return x.id === el.id;}).length;
            }, combined));
        return combined;
    }
  
    function getArrays() {
        return {
            arr1: [{
                id: 1,
                name: 'fred',
                title: 'boss'
            }, {
                id: 2,
                name: 'jim',
                title: 'nobody'
            }, {
                id: 3,
                name: 'bob',
                title: 'dancer'
            }],
            arr2: [{
                id: 1,
                wage: '300',
                rate: 'day'
            }, {
                id: 2,
                wage: '10',
                rate: 'hour'
            }, {
                id: 4,
                wage: '500',
                rate: 'week'
            }]
        };
    }
}());
<pre id="result"></pre>

关于javascript - 基于每个关键属性的连接合并/扩展javascript对象数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6059084/

相关文章:

javascript - 在不使用 css 文本转换的情况下,在用户键入时将文本字段中的文本大写?

ios - 类型转换数组的最有效方法

java - 对字节码和对象的澄清

javascript - 创建视频播放器(Quicktime 浏览器插件)React Elements,输出缺少的视频属性

python - 属性错误: 'str' object has no attribute (function)

javascript - 在 Javascript 中返回空数组

javascript - 使用 addEventListener 后看不到选中的 radio

javascript - Jquery 图像点击在 IE 中不起作用

java - 如何使用 Jackson 或任何其他 api 反序列化对象数组?

arrays - 如何将 "empty line"模式的文件拆分为变量数组? (仅使用 native bash)