Lodash 通过键查找和合并,同时保留特定键值

Lodash find by key and mergeWith while preserving specific key value

我有 2 个 collection,“parent”和“child”collection。

我需要:

Parent Object

"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
    }
  }

]

Child Object

"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

const result = _.mergeWith([], parentObjectOverrideable, childObject, (a, b) =>
  b === null || b === '' ? a : undefined
)

问题是,如果 cta_type 在 child object 上的位置不同,它也会覆盖 UID,所以你会得到这样的东西:

"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() 处理对象和数组的合并,并使用 [= 处理原语16=] 除非它是 null,而 b 不是 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 可以跳过中间值,将 _.mergeWith() 替换为 _.mergeAllWith(),它处理数组:

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>