【问题标题】:How to combine the values which is array of the same property in the object's array javascript如何在对象的数组javascript中组合相同属性数组的值
【发布时间】:2022-08-17 02:34:17
【问题描述】:

对于以下数组

const a = [
  {
    26: [0],
    27: [100],
    28: [0]
  },
  {
    26: [0],
    27: [100],
    28: [0]
  },
  {
    26: [0],
    27: [100],
    28: [0]
  }
]

我需要一个函数来合并具有对象中相同键的数组。

`const result = [{
26: [0,0,0],
27: [100,100,100],
28: [0,0,0]
}]`

标签: javascript arrays algorithm data-structures javascript-objects


【解决方案1】:

尝试使用reduce

const data = [{
    26: [0], 27: [100], 28: [0]
  },
  {
    26: [0], 27: [100], 28: [0]
  },
  {
    26: [0], 27: [100], 28: [0]
  }
];

const restructure = arr => 
  [arr.reduce((accumu, current) => {
    for (const [key, val] of Object.entries(current)) {
      accumu[key] = [...accumu[key] ?? '', ...val];
    }
    return accumu;
  }, {})];

console.log(JSON.stringify(restructure(data)));

【讨论】:

  • 为什么是空字符串?
  • @jarmod 这是spread syntax,它可以将字符串转换为数组
  • 这个问题没有字符串。为什么要引入字符串?
  • @jarmod您一定误解了一些东西。这实际上与该值是否具有字符串无关。当数据被分组时,我使用spread syntax 来合并数组。 accumu[key] 将是第一次未定义,所以不要直接使用[...accumu[key], ...val],而是使用nullish coalescing operator 将 undefined 替换为空字符串,然后spread syntax 会将空字符串转换为数组([...''] 将是转换为[]),然后与当前数组合并
  • 是的,我明白了,但它似乎有些模糊。你不能简单地使用accumu[key] = [...(accumu[key] ?? []), ...val];吗?
【解决方案2】:

您可以通过使用Array.forEach() 循环来简单地实现这一点。

现场演示

const a = [{
  26: [0],
  27: [100],
  28: [0]
}, {
  26: [0],
  27: [100],
  28: [0]
}, {
  26: [0],
  27: [100],
  28: [0]
}];

let resObj = {};

a.forEach(obj => {
    Object.keys(obj).forEach(key => {
    resObj[key] ? resObj[key].push(...obj[key]) : resObj[key] = [...obj[key]]
  })
});

console.log([resObj]);

【讨论】:

    【解决方案3】:

    保留一组实用函数可以使处理这类问题几乎是微不足道的。

    我的解决方案是编写这个函数:

    const combine = reduce (mergeWith (concat)) ({}) 
    

    基于我的实用函数reduceconcatmergeWith。然后它很简单:

    combine (a) //=> {26: [0, 0, 0], 27: [100, 100, 100], 28: [0, 0, 0]}
    

    const reduce = (f) => (init) => (xs) => xs .reduce ((a, x) => f (a, x), init)
    const concat = (a) => (b) => a .concat (b)
    const mergeWith = (f) => (a, b) => Object .fromEntries (
      [... new Set ([... Object .keys (a), ... Object .keys (b)])] .map (
        (k) => [k, k in a ? (k in b ? f (a [k]) (b [k]) : a [k]) : b [k]]
      )
    )
    
    const combine = reduce (mergeWith (concat)) ({}) 
    
    const a = [{26: [0], 27: [100], 28: [0]}, {26: [0], 27: [100], 28: [0]}, {26: [0], 27: [100], 28: [0]}]
    
    console .log (combine (a))
    .as-console-wrapper {max-height: 100% !important; top: 0}

    reduceconcat除了转换Array .prototype方法into pure功能.1在每种情况下,新函数都是完全柯里化的,例如,您将调用reduce (tranformer) (initialValue) (values) 而不是values .reduce (transformer, initialValue)。这种风格通常使编写函数更容易。

    mergeWith参与度更高。它执行两个对象的浅合并,只要两个对象都具有给定的键,就对两个对象的相关属性使用提供的函数,否则使用唯一提供的属性。

    一旦我们有了这些辅助函数,那么编写起来就变得非常简单了。我们用concat 配置mergeWith,并将这个结果函数和空对象传递给reduce

    const combine = reduce (mergeWith (concat)) ({})
    

    1reduce 不会像Array.prototype.reduce 那样向转换函数提供所有参数。这有充分的理由,不值得在这里讨论,但如果你想要它们,我们可以将实现简化为 const reduce (f) => (init) => (xs) => xs .reduce (f, init)

    【讨论】:

      【解决方案4】:

      这可以通过使用 Javascript 的内置 Array.Prototype.map() 方法轻松实现

      我的解决方案:

      function mergeSameKeys(arr) {
          let filteredObj = {}
      
          arr.map(obj => {
              let objKeys = Object.keys(obj);
      
              objKeys.map(key => {
                  if (!filteredObj.hasOwnProperty(key)) {
                      filteredObj[key] = obj[key]
                  } else {
                      filteredObj[key].push(...obj[key])
                  }
              })
      
          })
      
          return [filteredObj]
      }
      
      mergeSameKeys([{
          26: [0],
          27: [100],
          28: [0]
        },
        {
          26: [0],
          27: [100],
          28: [0]
        },
        {
          26: [0],
          27: [100],
          28: [0]
        }
      ])
      
      // returns [{
      // 26: [0,0,0],
      // 27: [100,100,100],
      // 28: [0,0,0]
      // }]
      

      该函数循环遍历提供的数组中的每个项目,并且对于每个对象,它使用Object.keys() 获取所有对象键的名称,并将它们作为存储在 objKeys 中的数组中的项目列表返回,然后循环遍历其中的每个键名称objKeys 并检查 filteredObj 变量是否包含此键作为属性。如果此检查返回 false,它会使用此键名在 filtersObj 中创建一个新键,并将创建的键的值设置为其原始对象中键的值。如果检查结果为真,它只需将其原始对象中的键值推送到 filtersObj 变量中的键值。使用Spread syntax (...),它会推送实际值而不是整个数组。该函数在最后一个数组中返回filteredObj变量,瞧。代码实现完成。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-26
        • 1970-01-01
        • 2013-10-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多