【问题标题】:Lodash find by key and mergeWith while preserving specific key valueLodash 通过 key 和 mergeWith 查找,同时保留特定的 key 值
【发布时间】:2021-04-22 14:08:11
【问题描述】:

我有 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)
}

知道怎么做吗?

【问题讨论】:

    标签: javascript reactjs lodash


    【解决方案1】:

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

    【讨论】:

    • 像魅力一样工作!希望我能给你一杯啤酒哈哈。你如何保持子对象的顺序?我选择了第一个选项
    • 第一个数组确定顺序。您可以更改提供给函数的数组的顺序,因此孩子将是第一个,并反转合并中的逻辑以从 a 获取值,只要它不是 null
    • 在合并两个数组之前,使用_.intersectionBy(child, parent, 'cta_type.ctaTypeNameUID') 只保留子项上存在的父项。
    • 更新了两个示例。
    • 酷!祝你一切顺利,我已经清理了这个问题。我相信很多人会发现这很有用
    猜你喜欢
    • 2017-11-21
    • 2020-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多