我有两个数组metaObjects
和justObjects
。
两个数组中的这些对象共有id
属性。
我想创建一个新数组,将来自不同数组中对象的属性组合起来
const metaObjects = [
{
id: 1,
metaProp: "metaProp1"
},
{
id: 2,
metaProp: "metaProp2"
}
];
const justObjects = [
{
id: 1,
justProp: "justProp1"
},
{
id: 2,
justProp: "justProp2"
}
];
这是我期望的结果
const result= [
{
id: 1,
metaProp: "metaProp1",
justProp: "justProp1"
},
{
id: 2,
metaProp: "metaProp2",
justProp: "justProp2"
}
];
我试图实现map of map
来实现这一目标
const combinedObject = justObjects.map(_w => {
return metaObjects.map(_m => {
if (_w.id === _m.id) {
return { ..._m, ..._w };
}
});
}, metaObjects);
console.log(combinedObject);
但是我收到以下错误
[ [ { id: 1, metaProp: 'metaProp1', justProp: 'justProp1' },
undefined ],
[ undefined,
{ id: 2, metaProp: 'metaProp2', justProp: 'justProp2' } ] ]
我不确定为什么每个数组的内部数组中都有一个undefined
。
另外,我需要弄平数组,使其接近上面的预期结果。
我听说过ramda的lens
可组合功能
可以在这里使用吗?
答案 0 :(得分:1)
这与customcommander的答案非常相似,但是选择使用groupBy
和values
而不是sortBy
和groupWith
。这对我来说更合乎逻辑,尤其是避免了不必要的sort
通话。
const {pipe, concat, groupBy, prop, values, map, mergeAll} = R
const joinOnId = pipe
( concat
, groupBy (prop ('id'))
, values
, map (mergeAll)
)
const metaObjects =
[ { id: 1, metaProp: "metaProp1" }
, { id: 2, metaProp: "metaProp2" }
, { id: 3, metaProp: "metaProp3" } // unique to `meta`
]
const justObjects =
[ { id: 1, justProp: "justProp1" }
, { id: 2, justProp: "justProp2" }
, { id: 4, justProp: "justProp4" } // unique to `just`
]
console.log
( joinOnId (metaObjects, justObjects)
)
.as-console-wrapper {
max-height: 100vh !important;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
请注意,可以轻松调整以接受其他属性名称:
const joinOn = (propName) =>
pipe
( concat
, groupBy (prop (propName))
, values
, map (mergeAll)
)
// ...
const joinOnId = joinOn ('id')
或使用任何常见的密钥生成功能:
const joinOn = (keyFn) =>
pipe
( concat
, groupBy (keyFn)
, values
, map (mergeAll)
)
// ...
const joinOnId = joinOn (prop ('id'))
答案 1 :(得分:0)
您可以搜索要与find()
合并的对象,然后使用Object.assign()
将它们合并在一起。假设该对象已经存在于metaObjects
中,如果不存在,则需要决定在这种情况下该怎么做。
const metaObjects = [
{
id: 1,
metaProp: "metaProp1"
},
{
id: 2,
metaProp: "metaProp2"
}
];
const justObjects = [
{
id: 1,
justProp: "justProp1"
},
{
id: 2,
justProp: "justProp2"
}
];
justObjects.forEach(item => {
let toMerge = metaObjects.find(obj => obj.id === item.id)
Object.assign(toMerge, item)
})
console.log(metaObjects)
如果metaObjects
可能很大,最好将其存储为键为id
的对象。然后,您可以直接查找它,而不必每次都进行搜索。
如果您不想更改metaObject,可以在map()
上justObjects
并创建一个新数组:
const metaObjects = [
{
id: 1,
metaProp: "metaProp1"
},
{
id: 2,
metaProp: "metaProp2"
}
];
const justObjects = [
{
id: 1,
justProp: "justProp1"
},
{
id: 2,
justProp: "justProp2"
}
];
let newArray = justObjects.map(item => {
let toMerge = metaObjects.find(obj => obj.id === item.id)
return Object.assign({}, toMerge, item)
})
// metaObjects unaffected
console.log(newArray)
答案 2 :(得分:0)
我认为您可以将两个数组简单地组合在一起,按id将对象分组(您需要先排序),最后合并每个组:
const {
map,
mergeAll,
groupWith,
eqBy,
prop,
concat,
sortBy,
pipe
} = R;
const metaObjects = [
{ id: 1,
metaProp: "metaProp1" },
{ id: 2,
metaProp: "metaProp2" }];
const justObjects = [
{ id: 1,
justProp: "justProp1" },
{ id: 2,
justProp: "justProp2" }];
const process = pipe(
concat,
sortBy(prop('id')),
groupWith(eqBy(prop('id'))),
map(mergeAll));
console.log(
process(metaObjects, justObjects)
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
答案 3 :(得分:0)
我将使用Array.prototype.reduce()
或for
循环,使用{将其中一个从具有Array
属性的对象id
转换为对象对象, {1}}作为密钥:
id
或者:
const merged = metaObjects.reduce((acc, cur) => {
acc[cur.id] = cur;
return acc;
}, {});
然后,迭代另一个对象,同时将其每个条目合并到上面刚刚创建的对象中:
const merged = {};
for (const obj of metaObjects) {
merged[obj.id] = obj;
}
最后,只需使用Object.values
将其转换回justObjects.forEach((obj) => {
merged[obj.id] = Object.assign({}, merged[obj.id], obj);
});
:
Array
示例:
Object.values(merged);
const metaObjects = [{
id: 1,
metaProp: "metaProp1"
},{
id: 2,
metaProp: "metaProp2"
}];
const justObjects = [{
id: 1,
justProp: "justProp1"
},{
id: 2,
justProp: "justProp2"
},{
id: 3,
justProp: "justProp3"
}];
// Create an object of one of the two using is id property:
/*
// Alternative using reduce:
const merged = metaObjects.reduce((acc, cur) => {
acc[cur.id] = cur;
return acc;
}, {});
*/
// Alternative using a for loop:
const merged = {};
for (const obj of metaObjects) {
merged[obj.id] = obj;
}
// Iterate the other one and merge it with the map you have just created:
justObjects.forEach((obj) => {
merged[obj.id] = Object.assign({}, merged[obj.id], obj);
});
// Convert it back to an Array of objects:
console.log(Object.values(merged));
请注意,即使两个对象中的任何一个包含一个.as-console-wrapper {
max-height: 100vh !important;
}
的条目,而在另一个对象中都不存在。