如何根据值合并两个不同长度的对象
How can I merge two objects of different lengths based on the values
我有两个对象数组,两个数组都包含键值对。我的 objective 是分配键值,如果一个键 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}
]
您可以使用 reduce 和 find
- 首先检查
arr1
中是否存在任何匹配的 _id
对应的名称
- 如果它存在,我们将该元素的值合并到最终输出中
- 否则只在输出中保留
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)
使用 _.flow()
that uses _.overArgs()
to convert each array to object with it's respective identifier (_id
or name
) as key (with _.keyBy()
), and merge them to a single object. Convert the object back to array, by mapping it while 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>
使用 vanilla JS,你可以 concat the arrays, and then use Array.reduce()
to convert the arrays to object using the _id
or name
as key, and combining items with the same key with object spread. Then convert back to array with 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)
在我看来,如果 一对 key value
array1
中只有 一对 key value
,则无需过于复杂化。只需转换为地图,然后 Array.map through array2
and Object.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)
我有两个对象数组,两个数组都包含键值对。我的 objective 是分配键值,如果一个键 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}
]
您可以使用 reduce 和 find
- 首先检查
arr1
中是否存在任何匹配的_id
对应的名称 - 如果它存在,我们将该元素的值合并到最终输出中
- 否则只在输出中保留
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)
使用 _.flow()
that uses _.overArgs()
to convert each array to object with it's respective identifier (_id
or name
) as key (with _.keyBy()
), and merge them to a single object. Convert the object back to array, by mapping it while 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>
使用 vanilla JS,你可以 concat the arrays, and then use Array.reduce()
to convert the arrays to object using the _id
or name
as key, and combining items with the same key with object spread. Then convert back to array with 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)
在我看来,如果 一对 key value
array1
中只有 一对 key value
,则无需过于复杂化。只需转换为地图,然后 Array.map through array2
and Object.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)