【问题标题】:Updating objects in an array (matching by value)更新数组中的对象(按值匹配)
【发布时间】:2020-08-11 21:35:28
【问题描述】:

有第一个数组(a)和第二个更新值(b)。需要通过 IDs 对象更新匹配并获取结果数组 (c)。我怎样才能让它变得简单快捷?

let a = [
    { id: 1, activated: '0' },
    { id: 2, activated: '0' },
    { id: 3, activated: '0' },
    { id: 4, activated: '0' },
  ]
let b = [
    { id: 2, activated: '1' },
    { id: 3, activated: '1' },
  ]
//Result array:
c = [ 
  { id: 1, activated: '0' },
  { id: 2, activated: '1' },
  { id: 3, activated: '1' },
  { id: 4, activated: '0' },
]

【问题讨论】:

  • 您要合并按 ID 排序的数组吗?
  • 你尝试了什么?请阅读StackOverflow.com/help 上的主题,了解有关在 SO 上提问的要求的更多信息。

标签: javascript arrays loops


【解决方案1】:

我建议您创建一个对象,其中键是快速访问的 id。

使用新创建的对象,您可以使用id 作为键从b 访问特定对象并更新对象。

最后,使用函数Object.values得到数组c

这是假设 b 的 id 存在于 a 中。

let a = [    { id: 1, activated: '0' },    { id: 2, activated: '0' },    { id: 3, activated: '0' },    { id: 4, activated: '0' }]
let b = [    { id: 2, activated: '1' },    { id: 3, activated: '1' }];
let newA = a.reduce((a, {id, ...rest}) => ({...a, ...{[id]: {id, ...rest}}}), {});

b.forEach(({id, activated}) => newA[id].activated = activated);

let c = Object.values(newA);
console.log(c);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • 太好了,谢谢!
  • @МаксимЮрченко yw!
【解决方案2】:

你可以使用Array.map,然后foreach对象,你可以使用Array.find通过ID检查它是否存在于arrayB中,如果存在则返回。

let a = [
    { id: 1, activated: '0' },
    { id: 2, activated: '0' },
    { id: 3, activated: '0' },
    { id: 4, activated: '0' },
];

let b = [
    { id: 2, activated: '1' },
    { id: 3, activated: '1' },
];

const c = a.map(e => {
    let newValue = b.find(n => e.id === n.id);

    if (!!newValue) {
        return newValue;
    }

    return e;
});

【讨论】:

    【解决方案3】:

    这就是我的处理方式:

    function mergeArray(...toMerge) {
      let output = {};
      toMerge.forEach(arr => {
        arr.forEach(item => {
          output[item.id] = item;
        });
      });
      return Object.values(output);
    }
    
    let a = [
        { id: 1, activated: '0' },
        { id: 2, activated: '0' },
        { id: 3, activated: '0' },
        { id: 4, activated: '0' },
      ];
    let b = [
        { id: 2, activated: '1' },
        { id: 3, activated: '1' },
      ];
    
    console.dir(mergeArray(a, b)) // can merge n-number of arrays.

    【讨论】:

      【解决方案4】:
      let c = a.map( aObj => {
        let found = b.find(bObj => bObj.id === aObj.id);
          if(found) return found;
          else return aObj;
      });
      

      【讨论】:

        【解决方案5】:

        您可以创建第二个数组的映射,以id 为键,然后当您将a 对象复制到c 中时,使用该映射将匹配的b 对象合并到它们中。

        let a = [{ id: 1, activated: '0' },{ id: 2, activated: '0' },{ id: 3, activated: '0' },{ id: 4, activated: '0' }]
        let b = [{ id: 2, activated: '1' },{ id: 3, activated: '1' }];
        
        let map = new Map(b.map(o => [o.id, o]));
        let c = a.map(o => ({...o, ...map.get(o.id)}));
        
        console.log(c);
        .as-console-wrapper { max-height: 100% !important; top: 0; }

        【讨论】:

          【解决方案6】:

          从数组 a 的 id 构建散列。通过在哈希中查找索引 b.id 来迭代数组 b,如果在 a 中找到实际大小,则该属性已激活。否则(在示例 id: 5 中)在旧数组 a 中不存在此 id 的条目,因此创建一个新条目并实现哈希。

          let a = [
              { id: 1, activated: '0' },
              { id: 2, activated: '0' },
              { id: 3, activated: '0' },
              { id: 4, activated: '0' },
            ];
          let b = [
              { id: 2, activated: '1' },
              { id: 3, activated: '1' },
              { id: 5, activated: '0' },
            ];
          
          let hash = a.flatMap(el => el.id);
          
          b.forEach(elem => {
              index = hash.indexOf(elem.id);
              if (index!=-1) 
                  a[index].activated=elem.activated;
               else {
                  a.push(elem);
                  hash.push(elem.id);
               }
          });
            
          console.log(a);  

          【讨论】:

            【解决方案7】:

            试试这个

            let a = [{
                id: 1,
                activated: '0'
              },
              {
                id: 2,
                activated: '0'
              },
              {
                id: 3,
                activated: '0'
              },
              {
                id: 4,
                activated: '0'
              },
            ]
            let b = [{
                id: 2,
                activated: '1'
              },
              {
                id: 3,
                activated: '1'
              },
            ]
            //Result array:
            c = [{
                id: 1,
                activated: '0'
              },
              {
                id: 2,
                activated: '1'
              },
              {
                id: 3,
                activated: '1'
              },
              {
                id: 4,
                activated: '0'
              },
            ]
            
            let result = a.map(e => {
              let p = b.find(be => be.id === e.id)
              if (p) e.activated = p.activated;
              return e
            })
            
            console.log(result)

            【讨论】:

            • 谁能解释为什么这不是理想的解决方案?我很想知道性能优化。
            • 不是我的反对意见,但find 代表一个循环,因此您有一个嵌套循环,总时间复杂度为 O(n²),虽然可以这样做在线性时间内。
            猜你喜欢
            • 2015-07-06
            • 2021-09-23
            • 2020-08-29
            • 1970-01-01
            • 2020-08-06
            • 2023-03-24
            • 2018-07-13
            • 2018-10-31
            • 2020-01-13
            相关资源
            最近更新 更多