【问题标题】:Merging two Javascript objects with similar keys合并两个具有相似键的 Javascript 对象
【发布时间】:2021-09-24 13:50:06
【问题描述】:

我需要合并两个恰好共享相似键的对象(obj1, obj2)。

obj1 = {
0:{"Example1": "Example1"},
1:{"Example1": "Example1"},
2:{"Example1": "Example1"}
}

obj2 = {
0:{"Example2": "Example2"},
1:{"Example2": "Example2"},
2:{"Example2": "Example2"}
}

预期结果:

obj3 = {
0:{"Example1": "Example1"},
1:{"Example1": "Example1"},
2:{"Example1": "Example1"},
3:{"Example2": "Example2"},
4:{"Example2": "Example2"},
5:{"Example2": "Example2"},
}

合并两个对象时的常用方法:

const obj3 = Object.assign({}, obj1, obj2);

问题:它们确实共享许多密钥,因此在obj3 中,只能找到obj2 的内容。

我的做法:

let obj3= Object.assign({}, obj1);
for(let i=0; i<obj2.length; i++) {
    obj3[obj3.length + i] = obj2[i];
}

问题:是否还有另一种更优雅的预定义方式来合并具有相似键的两个对象?

【问题讨论】:

  • 为什么这些对象放在首位?它们应该是数组。
  • @Andreas,这些对象是我正在使用的真实对象的近似值,它们大致属于这种组合。
  • 不要在标题中添加标签("... [JS]") -> What are tags, and how should I use them?
  • 不回答问题。它们应该是数组。然后就是一个简单的.concat()
  • 您应该将输入数据的实际示例添加为minimal reproducible example,以及预期的输出。

标签: javascript merge


【解决方案1】:

虽然我还是觉得obj1obj2应该是数组...

const obj1 = {
  0:{"Example1": "Example1"},
  1:{"Example1": "Example1"},
  2:{"Example1": "Example1"}
};

const obj2 = {
  0:{"Example2": "Example2"},
  1:{"Example2": "Example2"},
  2:{"Example2": "Example2"}
}
  
const result = Object.fromEntries(
                 Object.values(obj1)  // get the values of the first object
                   .concat(Object.values(obj2))  // get the values of the second object and add them to the values of the first
                   .map((value, index) => [ index, value ])  // re-index them
                   // or if you need actual copies of the "inner" objects
                   /*
                   .map((value, index) => [
                     index,
                     Object.assign({}, value)
                   ])
                   */
               );
  
console.log(result);

这是“更优雅”。也许……

【讨论】:

  • 您可以将.fromEntries().map() 替换为.reduce(),但我更喜欢表达性更强的版本。
【解决方案2】:

代码中的对象是键值对,而不是简单的列表(数组)。

从表面上看只有两种可能的情况:

  1. 您的对象有一个有意义的、唯一的键与它们相关联(例如,stackoverflow 上的这个问题的键是 69316153 - 查看 URL 栏)。在这种情况下,你真的不能合并两者,因为它们有冲突的键。想想这个网站上是否还有其他问题与这个问题的 ID 相同!
  2. 这些键没有意义,您很高兴为同一个对象重新分配不同的键。在这种情况下,要使用的正确数据结构是数组 (obj1 = [{"Example": "..."}, {"Example": "..."}])。

如果您的情况是后者,则此代码将起作用:

const obj3 = Object.values(obj1).concat(Object.values(obj2))

Object.values(obj) 返回一个值数组,丢弃所有键。

假设我们有:

 const obj1 = {
    1: { Name: "Apple" },
    2: { Name: "Watermelon" },
 };

 const obj2 = {
    2: { Name: "Pear" },
    5: { Name: "Tomato" }
 };

Object.values(obj1) 将返回[{ Name: "Apple" }, { Name: "Watermelon" }],而Object.values(obj2) 将返回[{ Name: "Pear" }, { Name: "Tomato" }]

使用const obj3 = Object.values(obj1).concat(Object.values(obj2)),您最终会得到:

obj3 = [
    { Name: "Apple" },
    { Name: "Watermelon" },
    { Name: "Pear" },
    { Name: "Tomato" }
];

【讨论】:

    【解决方案3】:

    因为您有键值映射而不是数组,所以您不能只组合对象。您唯一的方法是遍历所有键并将它们添加到最终结果中。

    例如类似的东西:

    const obj1 = {
      0:{"Example1": "Example1"},
      1:{"Example1": "Example1"},
      2:{"Example1": "Example1"}
    };
    
    const obj2 = {
      0:{"Example2": "Example2"},
      1:{"Example2": "Example2"},
      2:{"Example2": "Example2"}
    };
    
    function merge(...args) {
      return Object.fromEntries(                      // Create entries
         args                                         // From all arguments
         .flatMap(o => Object.values(o))              // Get values (discard keys)
         .map((element, index) => [ index, element ]) // Remap them
      );
    }
    
    console.log(merge(obj1, obj2));
    
    // Will output
    // {
    //  0: { Example1: "Example1" },
    //  1: { Example1: "Example1" },
    //  2: { Example1: "Example1" },
    //  3: { Example2: "Example2" },
    //  4: { Example2: "Example2" },
    //  5: { Example2: "Example2" }
    // }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-28
      • 1970-01-01
      • 1970-01-01
      • 2018-01-13
      • 1970-01-01
      • 2016-11-21
      相关资源
      最近更新 更多