如何基于值合并两个不同长度的对象

时间:2019-06-11 02:25:21

标签: javascript arrays ecmascript-6 lodash ecmascript-5

我有两个对象数组,两个数组都包含键,值对。我的目标是在一个键name的字符串值与另一个键_id的字符串值匹配的情况下,将键值从一个数组分配给第二个数组。

我已经尝试将两个数组组合成一个数组,并且只有一个对象数组,但是我仍然不确定如何根据键_id的匹配值将键和值分配给其他对象和name。我知道如何使用相同的键,但是我们如何基于不同的键和相同的值呢?  这可能是不好的设计和实践,但这就是数据返回的方式。可以吗我尝试使用lodash,传播操作,地图均未成功。

arr1 = [
{"_id": "electronics", "number": 35 },
{"_id": "house Appliances", "number": 5 },
{"_id": "nothing", "number":0}
]

arr2 = [
{"name": "electronics", "purpose": "entertainment", "price": 100},
{"name": "house Appliances", "purpose": "general", "price": 200},
{"name": "watches", "purpose": "time", "price": 30} ]

combinedArrObj = [
{"name": "electronics", "number": 35, "purpose": "entertainment", "price": 100},
{"name": "house Appliances", "purpose": "general", "price": 200, "number": 5}, 
{"name": "watches", "purpose": "time", "price": 30}
 ]

3 个答案:

答案 0 :(得分:1)

在我看来,如果您仅在key value中有一对一对 array1,就不需要太复杂。只需转换为地图,然后Array.maparray2Object.assign即可创建不带破折号等的合并。

const arr1 = [{"_id": "electronics", "number": 35 }, {"_id": "house Appliances", "number": 5 }]
const arr2 = [{"name": "electronics", "purpose": "entertainment", "price": 100},{"name": "house Appliances", "purpose": "general", "price": 200},{"name": "watches", "purpose": "time", "price": 30}]

let map = arr1.reduce((acc, {_id, number}) => (acc[_id] = number, acc), {})

let result = arr2.map(({name, ...rest}) => 
  Object.assign({ name }, rest, map[name] ? { number: map[name] } : {}))

console.log(result)

答案 1 :(得分:0)

您可以使用reduce and find

  • 首先检查_id中是否存在与相应名称匹配的arr1
  • 如果存在,我们将元素的值合并到最终输出中
  • 否则,仅将inp保留在输出中

let arr1 = [{"_id": "electronics", "number": 35 },"_id": "house Appliances", "number": 5 }]

let arr2 = [{"name": "electronics", "purpose": "entertainment", "price": 100},{"name": "house Appliances", "purpose": "general", "price": 200},{"name": "watches", "purpose": "time", "price": 30} ]

let final = arr2.reduce((op,inp)=>{
  let found = arr1.find(({_id})=>_id===inp.name)
  let name = inp.name
  op[name] = op[name] || {}
  if(found){
    let {_id, ...rest} = found
    op[name] = {...op[name], ...rest, ...inp}
  } else {
    op[name] = {...op[name], ...inp}
  }
  return op
},{})

console.log(final)

答案 2 :(得分:0)

使用_.flow()创建一个函数,该函数使用_.overArgs()将每个数组转换为对象,并以其各自的标识符(_idname)作为键(使用{{3} }),并将它们_.keyBy()合并为一个对象。通过merge _id字段mapping将对象转换回数组:

const { flow, partialRight: pr, overArgs, merge, keyBy, map, omit } = _

const combineArrays = flow(
  overArgs((...objs) => merge({}, ...objs), [
    arr1 => keyBy(arr1, '_id'),
    arr2 => keyBy(arr2, 'name')    
  ]),
  pr(map, o => omit(o, '_id'))
)

const arr1 = [{"_id": "electronics", "number": 35 }, {"_id": "house Appliances", "number": 5 }]
const arr2 = [{"name": "electronics", "purpose": "entertainment", "price": 100},{"name": "house Appliances", "purpose": "general", "price": 200},{"name": "watches", "purpose": "time", "price": 30}]
 
const combinedArrs = combineArrays(arr1, arr2)

console.log(combinedArrs)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

以及使用omitting的简短版本:

const { flow, overArgs, merge, keyBy, map, omit } = _

const combineArrays = flow(
  overArgs(merge, [keyBy('_id'), keyBy('name')]),
  map(omit('_id'))
)

const arr1 = [{"_id": "electronics", "number": 35 }, {"_id": "house Appliances", "number": 5 }]
const arr2 = [{"name": "electronics", "purpose": "entertainment", "price": 100},{"name": "house Appliances", "purpose": "general", "price": 200},{"name": "watches", "purpose": "time", "price": 30}]
 
const combinedArrs = combineArrays(arr1, arr2)

console.log(combinedArrs)
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>

使用香草JS,您可以lodash/fp个数组,然后使用concat_idname作为键并组合项目,将数组转换为对象与Array.reduce()使用相同的键。然后使用object spread转换回数组:

const combineArrays = (arr1, arr2) => Object.values(
  arr1.concat(arr2) // combine the arrays
    .reduce((r, { _id, ...o }) => { // clone the object and remove _id if exists
      const key = _id || o.name // the key is the _id or the name if _id doesn't exist

      r[key] = r[key] ? { ...r[key], ...o } : o // if the key exists on the accumulator combine with current item, if not set current item to the key

      return r;
    }, {})
)

const arr1 = [{"_id": "electronics", "number": 35 }, {"_id": "house Appliances", "number": 5 }]
const arr2 = [{"name": "electronics", "purpose": "entertainment", "price": 100},{"name": "house Appliances", "purpose": "general", "price": 200},{"name": "watches", "purpose": "time", "price": 30}]
 
const combinedArrs = combineArrays(arr1, arr2)

console.log(combinedArrs)