【问题标题】:How can I merge two objects of different lengths based on the values如何根据值合并两个不同长度的对象
【发布时间】:2019-10-25 09:37:59
【问题描述】:

我有两个对象数组,两个数组都包含键值对。我的目标是如果一个键name 的字符串值与另一个键_id 的字符串值匹配,则将键值从一个数组分配到第二个数组。

我尝试将两个数组合并为一个数组,并且只有一个数组与对象,但我仍然不确定如何根据键 _id 和 @ 的匹配值将键和值分配给其他对象987654324@。我知道如何使用相同的键,但是我们如何基于不同的键和相同的值来做到这一点? 这可能是糟糕的设计和实践,但这就是数据返回的方式。可行吗?我曾尝试使用 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}
 ]

【问题讨论】:

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


    【解决方案1】:

    在我看来,如果您只在array1 中有一个 key value 对,您不需要过于复杂化。只需转换为地图,然后 Array.maparray2Object.assign 即可创建没有 lodash 等的合并。

    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)

    【讨论】:

      【解决方案2】:

      你可以使用reduce和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)

      【讨论】:

        【解决方案3】:

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

        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>

        还有一个使用lodash/fp的简洁版本:

        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,您可以concat数组,然后使用Array.reduce()将数组转换为对象,使用_idname作为键,并将具有相同键的项目与object spread组合.然后用Object.values()转回数组:

        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)

        【讨论】:

          猜你喜欢
          • 2015-05-29
          • 1970-01-01
          • 2021-09-12
          • 2022-11-24
          • 2021-11-19
          • 2019-02-27
          • 1970-01-01
          • 2020-11-06
          • 2016-09-07
          相关资源
          最近更新 更多