【问题标题】:Merge property from an array of objects into another based on property value lodash根据属性值 lodash 将对象数组中的属性合并到另一个对象中
【发布时间】:2016-04-20 02:25:58
【问题描述】:

我有 2 个对象数组,它们每个都有一个共同的 id。我需要将数组 2 的对象的属性添加到对象数组 1,如果它们匹配 ids。

数组 1:

[
    {
        id: 1,
        name: tom,
        age: 24
    },
    {
        id: 2,
        name: tim,
        age: 25
    },
    {
        id: 3,
        name: jack,
        age: 24
    },

]

数组 2:

[
    {
        id: 1,
        gender: male,
        eyeColour: blue,
        weight: 150
    },
    {
        id: 2,
        gender: male,
        eyeColour: green,
        weight: 175
    },
    {
        id: 3,
        gender: male,
        eyeColour: hazel,
        weight: 200
    },

]

期望的结果:

[
    {
        id: 1,
        name: tom,
        age: 24,
        eyeColour: blue,
    },
    {
        id: 2,
        name: tim,
        age: 25,
        eyeColour: green,
    },
    {
        id: 3,
        name: jack,
        age: 24,
        eyeColour: hazel,
    },

]

我尝试使用 lodash _.merge 函数,但最终我将所有属性放入一个数组中,而我只想添加 eyeColour

【问题讨论】:

  • 这些不是关联数组。它们是对象数组。 JS中没有使用“关联数组”这个术语。
  • 删除了这个词,知道如何解决这个问题吗?

标签: javascript arrays object lodash


【解决方案1】:

纯 Javascript 的解决方案

这是一种更通用的解决方案,用于将两个具有不同属性的数组合并到一个对象中,并使用一个公共键和一些要添加的属性。

var array1 = [{ id: 1, name: 'tom', age: 24 }, { id: 2, name: 'tim', age: 25 }, { id: 3, name: 'jack', age: 24 }, ],
    array2 = [{ id: 1, gender: 'male', eyeColour: 'blue', weight: 150 }, { id: 2, gender: 'male', eyeColour: 'green', weight: 175 }, { id: 3, gender: 'male', eyeColour: 'hazel', weight: 200 }, ];

function merge(a, b, id, keys) {
    var array = [], object = {};

    function m(c) {
        if (!object[c[id]]) {
            object[c[id]] = {};
            object[c[id]][id] = c[id];
            array.push(object[c[id]]);
        }
        keys.forEach(function (k) {
            if (k in c) {
                object[c[id]][k] = c[k];
            }
        });
    }
    a.forEach(m);
    b.forEach(m);
    return array;
}

document.write('<pre>' + JSON.stringify(merge(array1, array2, 'id', ['name', 'age', 'eyeColour']), 0, 4) + '</pre>');

【讨论】:

  • 个人超级英雄 :-)
【解决方案2】:

Lodash 仍然是一个非常有用的实用程序包,但随着 ES6 的出现,它的一些用例不再那么引人注目了。

对于第一个数组中的每个对象(人),在第二个数组中找到具有匹配 ID 的对象(参见函数 findPerson)。然后将两者合并。

function update(array1, array2) {
  var findPerson = id => array2.find(person => person.id === id);

  array1.forEach(person => Object.assign(person, findPerson(person.id));
}

对于非 ES6 环境,使用传统语法重写箭头函数。如果Array#find 不可用,请编写您自己的或使用一些等效的。对于Object.assign,如果您更喜欢使用自己的等价物,例如_.extend

这会将array2 中的所有属性合并到array1。只合并eyeColour:

function update(array1, array2) {
  var findPerson = id => array2.find(person => person.id === id);

  array1.forEach(person => {
    var person2 = findPerson(person.id));
    var {eyeColour} = person2;
    Object.assign(person, {eyeColour});
  });
}

【讨论】:

    【解决方案3】:

    你可以使用pick在合并前只获取你想要的属性:

    var result = _.merge( arr1, _.map( arr2, function( obj ) {
        return _.pick( obj, 'id', 'eyeColour' );
    }));
    

    【讨论】:

    • @Andy 感谢您解决这个问题。
    • 对此不太确定。选择id有什么意义?它将覆盖第一个数组中的(可能不同的)id。
    【解决方案4】:

    刚刚注意到 Paul 在我处理答案时回答了,但无论如何我都会添加我非常相似的代码:

    var getEyeColour = function (el) { return _.pick(el, 'eyeColour'); }
    var out = _.merge(arr1, _.map(arr2, getEyeColour));
    

    DEMO

    【讨论】:

    • 是我遗漏了什么,还是这个解决方案假设两个数组中元素的顺序相同?
    • 是的,这是一个错误。 OP,您可能应该忽略这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-12
    • 1970-01-01
    • 2016-12-31
    • 2018-03-11
    • 1970-01-01
    • 2020-06-22
    相关资源
    最近更新 更多