【问题标题】:Union of 2 arrays using lodash使用 lodash 合并 2 个数组
【发布时间】:2018-09-06 03:21:06
【问题描述】:

我有以下 2 个数组:

    arr1 = [
            {
                "key1": "Value1"
            },
            {
                "key2": "Value2"
            },
            {
                "key3": "Test3"
            },
            {
                "key4": "Test4"
            },
            {
                "key5": "Test5"
            },
            {
                "key6": "Test6"
            },
            {
                "key7": "Test7"
            }
        ]

第二个数组是

    arr2 = [
            {
                "key3": "Value3-changed"
            },
            {
                "key6": "Value6-changed"
            }

        ]

现在,一旦我加入 2 个数组,结果将是

   resultArr = [
        {
            "key1": "Value1"
        },
        {
            "key2": "Value2"
        },
        {
            "key3": "Value3-changed"
        },
        {
            "key4": "Test4"
        },
        {
            "key5": "Test5"
        },
        {
            "key6": "Value6-changed"
        },
        {
            "key7": "Test7"
        }
    ]

我看到了Lodash union of arrays of objects 的解决方案。但就我而言,关键是不同的。任何,解决这个问题的指针?我试图使用 lodash _.unionBy 然后 _.uniqWith 但没有得到想要的结果。

谢谢, 安迪

【问题讨论】:

标签: javascript arrays node.js lodash


【解决方案1】:

不需要 lodash。首先将两个数组简化为一个对象,稍后出现的键会覆盖任何先前设置的值:

const obj = [...arr1, ...arr2].reduce((acc,cur) => Object.assign(acc, cur), {});
// {key1: value1, ...}

编辑,更简单:

const obj = Object.assign({}, ...arr1, ...arr2);

然后将键映射回对象数组:

const resultArray = Object.keys(obj)
   .sort() // if alphanumeric order of keys matters to you
   .map(key => { const o={}; o[key]=obj[key]; return o;});

【讨论】:

  • 在我看来,它们应该是独一无二的,即。 arr2 中的 key3 覆盖 arr1 中的 key3 等。
  • 那么 31piy 是什么意思?
  • 所以要清楚,这个代码只有唯一的键。你说应该有重复?
  • 看OP的例子,你是对的,似乎不应该有重复,而是第二个数组中的值应该覆盖第一个数组中的值。
  • 是的,这就是这里发生的事情。 obj 将只有一个键。 Object.assign({key3: 'old'}, {key3: 'new'}) ==> {key3: 'new'}
【解决方案2】:

你可以像这样在没有 lodash 的情况下做到这一点:

(推送新对象,或更新现有对象。

let arr1 = [
    {
        "key1": "Value1"
    },
    {
        "key2": "Value2"
    },
    {
        "key3": "Test3"
    },
    {
        "key4": "Test4"
    },
    {
        "key5": "Test5"
    },
    {
        "key6": "Test6"
    },
    {
        "key7": "Test7"
    },
]

let arr2 = [
    {
        "key3": "Value3-changed"
    },
    {
        "key6": "Value6-changed"
    },
    {
        "key10": "Value10-new"
    },
]

for (let obj of arr2) {
    let keyName = Object.keys(obj)[0];
    let existingObject = arr1.find(x => Object.keys(x)[0] === keyName );
    
    if (existingObject) {
        // object with same key exists. So we update it.
        existingObject[keyName] = obj[keyName];
    } else {
        // key was not found, this is a new object, let's add it.
        arr1.push(obj);
    }
}

console.log(arr1)

当然,可能有更优雅的方式来做到这一点。

【讨论】:

  • 感谢@Pac0 的帮助。我接受了你的回答。
【解决方案3】:

如果您有权访问 ... 扩展运算符:

map(chunk(toPairs(assign(...arr1, ...arr2))), fromPairs)

否则:

map(chunk(toPairs(spread(assign)(concat(arr1, arr2)))), fromPairs)

这很丑,但可以。


Lodash 插件

_.mixin({
  'assignPairsChunkAndMapObjects' : function(arr1, arr2) {
    return _.map(_.chunk(_.toPairs(_.assign(...arr1, ...arr2))), _.fromPairs);
  },
  'assignPairsChunkAndMapObjectsChained' : function(arr1, arr2) {
    return _.chain(_.assign(...arr1, ...arr2)).toPairs().chunk().map(_.fromPairs).value();
  }
});

【讨论】:

  • 但这会创建一个包含所有键的对象。 OP 想要原始中每个对象的数组,其中包含更新的键值对。
  • 我将您的代码转换为 Lodash 插件,并添加了完成相同任务的链式版本。
【解决方案4】:

使用原生 javascript,您可以使用 for ..in 和 map 函数实现相同的功能

var arr1 = [{
    "key1": "Value1"
  },
  {
    "key2": "Value2"
  },
  {
    "key3": "Test3"
  },
  {
    "key4": "Test4"
  },
  {
    "key5": "Test5"
  },
  {
    "key6": "Test6"
  },
  {
    "key7": "Test7"
  }
]
var arr2 = [{
    "key3": "Value3-changed"
  },
  {
    "key6": "Value6-changed"
  }

];
// get object keys from both
var getArr2Keys = arr2.map(function(items) {
  for (let keys in items) {
    return keys;
  }
});

var getArr1Keys = arr1.map(function(items) {
  for (let keys in items) {
    return keys;
  }
});


// iterate over the newly created object and check if the key matched
getArr2Keys.forEach(function(itemArr2, index) {
  var x = getArr1Keys.findIndex(function(itemArr1) {
    return itemArr2 === itemArr1;
  })
  // replace the key value of arr1 with value from arr2
  arr1[x][itemArr2] = arr2[index][itemArr2]

})

console.log(arr1)

【讨论】:

    【解决方案5】:

    您可以创建一个 mixin 来迭代第一个数组并将其与第二个数组合并。

    _.mixin({
      'mergeObjectList' : function(arr1, arr2) {
        return _.map(arr1, function(obj) {
          Object.keys(obj).forEach(key => {
            var found = _.find(arr2, x => Object.keys(x).indexOf(key) > -1);
            if (found != null) {
              return _.merge(obj, found);
            }
          });
          return obj;
        });
      }
    });
    
    var arr1 = [
      { "key1": "Value1" },
      { "key2": "Value2" },
      { "key3": "Test3" },
      { "key4": "Test4" },
      { "key5": "Test5" },
      { "key6": "Test6" },
      { "key7": "Test7" }
    ];
    
    var arr2 = [
      { "key3": "Value3-changed" },
      { "key6": "Value6-changed" }
    ];
    
    var arr3 = _.mergeObjectList(arr1, arr2);
    
    document.body.innerHTML = JSON.stringify(arr3, null, 4);
    body { font-family: monospace; white-space: pre; }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>

    【讨论】:

      【解决方案6】:

      还可以使用mapfind数组方法。

      在 ES5 中

      var arr1 = [{
          "key1": "Value1"
        }, {
          "key2": "Value2"
        }, {
          "key3": "Test3"
        }, {
          "key4": "Test4"
        }, {
          "key5": "Test5"
        }, {
          "key6": "Test6"
        }, {
          "key7": "Test7"
        }],
      
        arr2 = [{
          "key3": "Value3-changed"
        }, {
          "key6": "Value6-changed"
        }],
      
        key = '';
      
      var result = arr1.map(function(item) {
        key = Object.keys(item)[0];
        return arr2.find(function(v) {
          return v[key]
        }) || item;
      });
      
      console.log(result);

      在 ES6 中

      const arr1 = [{
          "key1": "Value1"
        }, {
          "key2": "Value2"
        }, {
          "key3": "Test3"
        }, {
          "key4": "Test4"
        }, {
          "key5": "Test5"
        }, {
          "key6": "Test6"
        }, {
          "key7": "Test7"
        }],
      
        arr2 = [{
            "key3": "Value3-changed"
          }, {
            "key6": "Value6-changed"
          }
      
        ];
      
      let result = arr1.map(item => {
        let key = Object.keys(item)[0];
        return arr2.find(v => v[key]) || item;
      });
      
      console.log(result);

      【讨论】:

        猜你喜欢
        • 2021-12-04
        • 1970-01-01
        • 1970-01-01
        • 2016-09-15
        • 2021-12-10
        • 2017-03-12
        • 1970-01-01
        • 2020-09-16
        • 2017-06-08
        相关资源
        最近更新 更多