【问题标题】:Merge/Add an object into an array - Javscript将对象合并/添加到数组中 - Javascript
【发布时间】:2021-01-11 20:46:51
【问题描述】:

我有两个对象数组。我的目标是根据“id”将第二个数组中的对象替换为第一个数组。我有一个可行的解决方案,但如果找不到值,我想通过将对象添加到第一个数组来扩展它。请指教。

function mergeById(arr) {
  return {
    with: function(arr2) {
      return _.map(arr, item => {
        return _.find(arr2, obj => obj.id === item.id) || item
      })
    }
  }
}

var result = mergeById([{
      id: '124',
      name: 'qqq'
    },
    {
      id: '589',
      name: 'www'
    },
    {
      id: '567',
      name: 'rrr'
    }
  ])
  .with([{
    id: '124',
    name: 'ttt'
  }, {
    id: '45',
    name: 'yyy'
  }])

console.log(result);

/**
[
  {
    "id": "124",
    "name": "ttt"
  },
  {
    "id": "589",
    "name": "www"
  },
  {
    "id": "567",
    "name": "rrr"
  },
  {
    id: '45',
    name: 'yyy'
  }
]
**/
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.20/lodash.min.js"></script>

请指教。

【问题讨论】:

    标签: javascript arrays lodash


    【解决方案1】:

    您需要过滤第二个数组并添加没有公共id的值。

    function mergeById(arr) {
        return {
            with: function(arr2) {
                return [
                    ..._.map(arr, item => _.find(arr2, obj => obj.id === item.id) || item),
                    ..._.filter(arr2, item => !_.some(arr, obj => obj.id === item.id))
                ];
            }
        }
    }
    
    var result = mergeById([{ id: '124', name: 'qqq' }, { id: '589', name: 'www' }, { id: '567', name: 'rrr' } ])
          .with([{ id: '124', name: 'ttt' }, { id: '45', name: 'yyy' }]);
    
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.20/lodash.min.js"></script>

    使用Map 和每个数组的单个循环的更短的方法。

    function mergeById(array) {
        const
            add2map = (m, o) => m.set(o.id, o),
            map = array.reduce(add2map, new Map);
        return {
            with: function(array2) {
                return Array.from(array2
                    .reduce(add2map, map)
                    .values()
                );
            }
        }
    }
    
    var result = mergeById([{ id: '124', name: 'qqq' }, { id: '589', name: 'www' }, { id: '567', name: 'rrr' } ])
          .with([{ id: '124', name: 'ttt' }, { id: '45', name: 'yyy' }]);
    
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

    • 一如既往地谢谢你:)
    【解决方案2】:

    使用_.differenceBy(arr2, arr, 'id') 查找出现在arr2 中且在arr 中没有对应项id 的所有项目,并将它们连接到_.map() 操作的结果。

    注意:不是每次迭代都使用_.find() (O(n)),而是使用_.keyBy() (O(n)) 迭代一次arr2 以创建字典{ [id]: item },然后获取O 中的项目(1).

    const mergeById = arr => ({
      with(arr2) {
        const arr2Dict = _.keyBy(arr2, 'id')
    
        return _.map(arr, item => arr2Dict[item.id] || item)
          .concat(_.differenceBy(arr2, arr, 'id'))
      }
    })
    
    const result = mergeById([{ id: '124', name: 'qqq' }, { id: '589', name: 'www' }, { id: '567', name: 'rrr' } ])
          .with([{ id: '124', name: 'ttt' }, { id: '45', name: 'yyy' }])
    
    console.log(result)
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.20/lodash.min.js"></script>

    您可以在一个循环中替换/添加,方法是连接两个数组,减少为 Map,然后将 id 的项目添加到 Map:

    const mergeById = arr => ({
      with(arr2) {
        return Array.from(
          [...arr, ...arr2]
            .reduce((r, o) => r.set(o.id, o), new Map)
            .values()
        )
      }
    })
    
    const result = mergeById([{ id: '124', name: 'qqq' }, { id: '589', name: 'www' }, { id: '567', name: 'rrr' } ])
          .with([{ id: '124', name: 'ttt' }, { id: '45', name: 'yyy' }])
    
    console.log(result)
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.20/lodash.min.js"></script>

    【讨论】:

    • 为什么是两个? ?
    • 更具体
    • 抱歉,您的代码中有两个问号。看起来你现在编辑了它。谢谢
    • 这两个问号?? 被称为Nullish coalescing operator,但是这个答案没有必要,我认为它们可能会混淆这就是我编辑它们的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-13
    • 1970-01-01
    • 1970-01-01
    • 2019-09-02
    • 2020-10-22
    • 2016-09-05
    • 2023-01-11
    相关资源
    最近更新 更多