Lodash通过键和mergeWith查找,同时保留特定键值 [英] Lodash find by key and mergeWith while preserving specific key value

查看:40
本文介绍了Lodash通过键和mergeWith查找,同时保留特定键值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆