【问题标题】:How do I split an array of objects into multiple arrays of objects while filtering for duplicates?如何在过滤重复项时将对象数组拆分为多个对象数组?
【发布时间】:2021-12-12 08:10:59
【问题描述】:

好的,我知道这是一项艰巨的任务。

这是我的情况,假设我有下面的对象数组

var fullData = [{foo1: bar1, foo2: bar2, foo3: bar3}, 
                {foo1: bar4, foo2: bar5, foo3: bar6}, 
                {foo1: bar7, foo2: bar8, foo3: bar6}]

我希望将其更改为

[{name: bar1, label: bar1}, {name: bar4, label: bar4},{name: bar7, label: bar7}]

[{name: bar2, label: bar2}, {name: bar5, label: bar5},{name: bar8, label: bar8}]

[{name: bar3, label: bar3}, {name: bar6, label: bar6}]

我从另一个将 AoO 拆分为数组对象的线程中找到了以下内容。

var result = res.body.reduce((r, o) => {
                    Object.entries(o).forEach(([k, v]) => (r[k] = r[k] || []).push(v));
                    return r;
                }, Object.create(null));

但它不会过滤重复项,也不会按照我上面标记的方式格式化数据,而且我无法弄清楚上面的函数是如何工作的。对于重复项,我选择在 result 的每个单独元素上使用来自 lodash 的 _.uniq,但被困在“名称”和“标签”格式上,所以我想如果有可能我会问比我更有经验的程序员一种将所有这些合并到一个函数中的方法。

【问题讨论】:

    标签: javascript arrays object lodash


    【解决方案1】:

    您可以在将元素推送到数组之前添加检查数组是否包含元素,方法是这样更改:

    ([k, v]) => (r[k] = r[k] || []).push(v)
    

    到这里:

    r[k] = r[k] || []
    if(!r[k].includes(v)) r[k].push(v)
    

    var fullData = [{foo1: 'bar1', foo2: 'bar2', foo3: 'bar3'}, 
                    {foo1: 'bar4', foo2: 'bar5', foo3: 'bar6'}, 
                    {foo1: 'bar7', foo2: 'bar8', foo3: 'bar6'}]
                    
    var result = fullData.reduce((r, o) => {
       Object.entries(o).forEach(([k, v]) => {
          r[k] = r[k] || []
          if(!r[k].includes(v)) r[k].push(v)
       });
       return r;
     }, 
     Object.create(null));
    
    console.log(result)

    如果您希望将结果展平为数组数组,您可以遍历上一个结果的条目并将其推送到新数组中

    var fullData = [{foo1: 'bar1', foo2: 'bar2', foo3: 'bar3'}, 
                    {foo1: 'bar4', foo2: 'bar5', foo3: 'bar6'}, 
                    {foo1: 'bar7', foo2: 'bar8', foo3: 'bar6'}]
                    
    var tmpResult = fullData.reduce((r, o) => {
       Object.entries(o).forEach(([k, v]) => {
          r[k] = r[k] || []
          if(!r[k].includes(v)) r[k].push(v)
       });
       return r;
     }, 
     Object.create(null));
    
    var result = [];
    Object.keys(tmpResult).forEach(k => {
      result.push(
        tmpResult[k].map(v => ({name: k, value: v}))
      );
    })
    console.log(result)

    我知道这似乎效率低下,但我确信这值得一试。

    【讨论】:

    • 太棒了!谢谢,这已经摆脱了这么多冗余代码。您是否也知道如何在我上面提到的每个“条”之前添加“名称”和“标签”?
    • @profiter 我已经添加了代码以将值提取为您问题中的格式。如果这有帮助,请投赞成票并接受这个答案。谢谢。
    • 不幸的是,这现在摆脱了重复过滤。我尝试过类似的事情并且遇到了同样的问题。你知道另一种方法吗?
    • 太棒了,谢谢你的作品。我还找到了另一种使您以前的代码工作的方法,只需添加此行const isFound = r[k].some(element => { if (element.name == v) return true }) 并将您的 if 语句修改为此if (!isFound) r[k].push({ name: v, label: v })。无论如何,非常感谢您的帮助,我将支持并接受您的回答:)
    猜你喜欢
    • 2021-04-21
    • 2021-11-02
    • 2023-03-22
    • 1970-01-01
    • 2023-02-03
    • 1970-01-01
    • 2019-12-28
    • 2021-09-07
    • 1970-01-01
    相关资源
    最近更新 更多