Lodash通过键和mergeWith查找,同时保留特定键值 [英] Lodash find by key and mergeWith while preserving specific key value
问题描述
我有2个收藏,父"收藏和孩子"集合.
I have 2 collections, the "parent" and the "child" collection.
我需要:
-
通过ctaTypeNameUID查找父项中的子项
Find child items in the parent by ctaTypeNameUID
如果子对象的值不为null,则子对象应覆盖父对象.
The parent object should be overwritten by the child object if the child object values are not null.
保持孩子的秩序
仅保留子项中存在的父项+子项中的自定义项
keep just the parent items that exist on the child + custom ones from child
父对象
"parentObjectOverrideable": [{
"cta_type": {
"title": null,
"ctaTypeNameUID": "enjoy-new-york",
"form-url": "F-2009",
"city": "New York",
"address": null
}
},
{
"cta_type": {
"title": null,
"ctaTypeNameUID": "enjoy-london",
"form-url": "F-2010",
"city": "London",
"address": null
}
}
]
子对象
"childObject": [{
"cta_type": {
"title": "Enjoy London",
"ctaTypeNameUID": "enjoy-london",
"form-url": "F-2009",
"city": null,
"address": null
}
},
{
"cta_type": {
"title": "Enjoy New York",
"ctaTypeNameUID": "enjoy-new-york",
"form-url": "F-22827166628",
"city": null,
"address": null
}
},
]
我尝试过使用Lodash中的_mergeWith
I have tried using _mergeWith from Lodash
const result = _.mergeWith([], parentObjectOverrideable, childObject, (a, b) =>
b === null || b === '' ? a : undefined
)
问题在于,如果cta_type的位置在子对象上不同,它也会覆盖UID,因此您将获得如下信息:
the problem is that if the position of the cta_type is different on the child object, it overrides the UID as well so you get something like this:
"parentObjectOverrideable": [{
"cta_type": {
"title": "Enjoy London",
,
"ctaTypeNameUID": "enjoy-new-york",
"form-url": "F-2009"
"city": null "address": null
}
},
{
"cta_type": {
"title": "Enjoy New York",
"ctaTypeNameUID": "enjoy-london",
"form-url": "F-2010",
"city": null,
"address": null
}
}
]
我也尝试这样做
const overrideObject = (objA, objB) => {
const newObject = { ...objB
}
Object.keys(objA).forEach((key) => {
if (objA[key]) {
newObject[key] = objA[key]
}
})
console.log(newObject)
}
有什么想法吗?
推荐答案
将项目组合到单个数组中,将其分组为 cta_type.ctaTypeNameUID
,然后将每个组合并为一个对象,从而使 _.mergeBy()
处理合并的对象和数组,并使用 a
处理基元,除非它为 null
和 b
不是 undefined
.
Concat the items to a single array, group it cta_type.ctaTypeNameUID
, and the merge each group to a single object, letting _.mergeBy()
handle merging objects and arrays, and handling primitives by using a
unless it's null
, and b
is not undefined
.
const { flow, concat, groupBy, flatMap, mergeWith, isObject, isUndefined, isNull, intersectionBy } = _
const fn = flow(
concat,
arr => groupBy(arr, 'cta_type.ctaTypeNameUID'),
groups => flatMap(groups, group => mergeWith({}, ...group, (a, b, k) => {
if(isObject(a) || isObject(b)) return undefined
return !isUndefined(b) && isNull(a) ? b : a
})),
)
const parentObjectOverrideable = [{"cta_type":{"title":null,"ctaTypeNameUID":"enjoy-new-york","form-url":"F-2009","city":"New York","address":null}},{"cta_type":{"title":null,"ctaTypeNameUID":"enjoy-london","form-url":"F-2010","city":"London","address":null}}]
const childObject = [{"cta_type":{"title":"Enjoy London","ctaTypeNameUID":"enjoy-london","form-url":"F-2009","city":null,"address":null}},{"cta_type":{"title":"Enjoy New York","ctaTypeNameUID":"enjoy-new-york","form-url":"F-22827166628","city":null,"address":null}}]
const result = fn(
childObject,
intersectionBy(parentObjectOverrideable, childObject, 'cta_type.ctaTypeNameUID')
)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous"></script>
使用lodash/fp,您可以跳过中间值,并用处理数组的 _.mergeAllWith()
替换 _.mergeWith()
:
With lodash/fp you can skip the intermediate values, and replace _.mergeWith()
with _.mergeAllWith()
, which handles arrays:
const { flow, intersectionBy, concat, groupBy, flatMap, mergeAllWith, isObject, isUndefined, isNull } = _
const fn = flow(
concat,
groupBy('cta_type.ctaTypeNameUID'),
flatMap(mergeAllWith((a, b) => {
if(isObject(a) || isObject(b)) return undefined
return !isUndefined(b) && isNull(a) ? b : a
}))
)
const parentObjectOverrideable = [{"cta_type":{"title":null,"ctaTypeNameUID":"enjoy-new-york","form-url":"F-2009","city":"New York","address":null}},{"cta_type":{"title":null,"ctaTypeNameUID":"enjoy-london","form-url":"F-2010","city":"London","address":null}}]
const childObject = [{"cta_type":{"title":"Enjoy London","ctaTypeNameUID":"enjoy-london","form-url":"F-2009","city":null,"address":null}},{"cta_type":{"title":"Enjoy New York","ctaTypeNameUID":"enjoy-new-york","form-url":"F-22827166628","city":null,"address":null}}]
const result = fn(
childObject,
intersectionBy('cta_type.ctaTypeNameUID', parentObjectOverrideable, childObject)
)
console.log(result)
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>
这篇关于Lodash通过键和mergeWith查找,同时保留特定键值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!