Lodash 按键查找并合并,同时保留特定键值

IT技术 javascript reactjs lodash
2021-05-09 13:35:50

我有 2 个集合,“父”和“子”集合。

我需要:

  • 通过 ctaTypeNameUID 在父项中查找子项

  • 如果子对象值不为空,则父对象应被子对象覆盖。

  • 保持孩子的秩序

  • 仅保留子项上存在的父项 + 子项中的自定义项

父对象

"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

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

问题是,如果 cta_type 在子对象上的位置不同,它也会覆盖 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)
}

知道如何做到这一点吗?

1个回答

将项目连接到一个数组,将它分组cta_type.ctaTypeNameUID,然后将每个组合并到一个对象,让_.mergeBy()处理合并对象和数组,并通过使用处理原语,a除非它是nullb不是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>