【问题标题】:how to use javascript reduce on an array of objects [duplicate]如何在对象数组上使用javascript减少[重复]
【发布时间】:2019-07-20 22:02:46
【问题描述】:

我有一个对象数组,其中每个对象都有一个 id 键。 其中一些对象有重复出现的 id,我想删除那些重复出现的对象。

例如:

let array = [{
    "id": "123",
    "country": "Brazil",
    "address": "xyz abc",
    "date": "Dec 17, 1995, 9:45:17 PM"
  },
  {
    "id": "443",
    "country": "Russia",
    "address": "qwd qwd qwdqw",
    "date": "Dec 17, 1965, 9:45:17 PM"
  },
  {
    "id": "123",
    "country": "Canada",
    "address": "ktktkt",
    "date": "Dec 17, 1925, 9:45:17 PM"
  },
.
.
.
{}]

在上面的数组中,由于索引 0 和索引 2 共享相同的 id 键值,我想将它们从数组中完全删除。

  • 我正在寻找复杂度最佳的代码,只有线性 (O(n))。

【问题讨论】:

标签: javascript


【解决方案1】:

既然你想完全删除重复的值,你可以试试这个。先找到重复,然后过滤原始数组。

let array = [{
    "id": "123",
    "country": "Brazil"
  },{
    "id": "443",
    "country": "Russia"
  },{
    "id": "123",
    "country": "Canada"
  },{
    "id": "123",
    "country": "Canada"
  },{
    "id": "345",
    "country": "UK"
  }];

const removeDups = (data) => {
	
	const dups = data.reduce((acc, { id }) => {
		acc[id] = (acc[id] || 0) + 1;
		return acc;
	}, {});

	return data.filter(({ id }) => dups[id] === 1);
}

console.log(removeDups(array));

【讨论】:

  • 我真的很喜欢这个分离重复计数然后进入过滤器的功能。 removeDups() 的复杂度是多少?
  • @clusterBuddy 谢谢,我相信是 O(n)。
  • 谢谢亚历克斯。我正在学习如何使用reduce,我可以在这个函数中使用一个计数器来计算reducer 中国家名称的再次出现吗?
  • @clusterBuddy 是的,您可以使用 country 属性而不是 id。所以你最终会得到一个对象,国家作为键,重复出现作为值。
【解决方案2】:

我不知道,也许是这个?:

array.filter(function(d,i){return !this[d.id] && (this[d.id] = d.id)},{})

【讨论】:

    【解决方案3】:

    不需要reduce,只需排序和过滤:

    let array = [{
        "id": "123",
        "country": "Brazil",
        "address": "xyz abc",
        "date": "Dec 17, 1995, 9:45:17 PM"
      },
      {
        "id": "443",
        "country": "Russia",
        "address": "qwd qwd qwdqw",
        "date": "Dec 17, 1965, 9:45:17 PM"
      },
      {
        "id": "123",
        "country": "Canada",
        "address": "ktktkt",
        "date": "Dec 17, 1925, 9:45:17 PM"
      },
      
    ]
    
    
    const output = array.sort((a, b) => a.id - b.id).filter((item, index, sorted) => {
      const before = sorted[index - 1] || {}
      const after = sorted[index + 1] || {}
    
      return item.id !== after.id && item.id !== before.id
    })
    
    console.log(output);

    【讨论】:

      【解决方案4】:

      您根本不需要reduce - 一个简单的for 循环就可以完成这项工作:

      let array = [{
          "id": "123",
          "country": "Brazil",
          "address": "xyz abc",
          "date": "Dec 17, 1995, 9:45:17 PM"
        },
        {
          "id": "443",
          "country": "Russia",
          "address": "qwd qwd qwdqw",
          "date": "Dec 17, 1965, 9:45:17 PM"
        },
        {
          "id": "123",
          "country": "Canada",
          "address": "ktktkt",
          "date": "Dec 17, 1925, 9:45:17 PM"
        }
      ]
      
      array.forEach(i => {
        let found = false
        array.forEach(j => {
          if (j == i) {
            found++;
          }
        });
        if (found) {
          array.forEach((k, l) => {
            if (k == i) {
              array.splice(l, 1);
              l--;
            }
          });
        }
      });
      
      console.log(array);

      【讨论】:

      • 嘿,杰克,谢谢您的回复,请注意您的解决方案具有指数级复杂性。
      • 对不起@clusterBuddy 我不太擅长符合复杂性的算法。
      【解决方案5】:

      您可以使用Map,如果存在,请将 mapeed 数组的长度设置为零。最后连接所有数组。

      var array = [{ id: "123", country: "Brazil", address: "xyz abc", date: "Dec 17, 1995, 9:45:17 PM" }, { id: "443", country: "Russia", address: "qwd qwd qwdqw", date: "Dec 17, 1965, 9:45:17 PM" }, { id: "123", country: "Canada", address: "ktktkt", date: "Dec 17, 1925, 9:45:17 PM" }],
          result = [].concat(...array.map((m => (o, i) => {
              var temp = [];
              if (m.has(o.id)) {
                  m.get(o.id).length = 0;
              } else {
                  m.set(o.id, temp = [o]);
              }
              return temp;
         })(new Map)))
      
      console.log(result);

      【讨论】:

        【解决方案6】:

        您可以简单地初始化一个count 对象并使用简单的forEach 循环填充它,然后只需使用filter

        let arr = [{ id: "123", country: "Brazil", address: "xyz abc", date: "Dec 17, 1995, 9:45:17 PM" }, { id: "443", country: "Russia", address: "qwd qwd qwdqw", date: "Dec 17, 1965, 9:45:17 PM" }, { id: "123", country: "Canada", address: "ktktkt", date: "Dec 17, 1925, 9:45:17 PM" }]
        
        count = {}
        
        arr.forEach(obj => {
          if (count[obj.id]) {
              count[obj.id] += 1
          } else {
              count[obj.id] = 1
          } 
        })
        
        
        
        console.log(arr.filter(obj => count[obj.id] === 1))

        运行时间(代码复杂度):O(N)

        【讨论】:

          【解决方案7】:

          一种解决方案是将输入 array 聚合到键/值映射,其中值是共享相同 id 的项目列表。然后,您将通过 Object.values() 从该映射中提取一个数组,过滤包含多个项目的值,然后将这些单个项目映射到最终输出:

          let array = [{
              "id": "123",
              "country": "Brazil",
              "address": "xyz abc",
              "date": "Dec 17, 1995, 9:45:17 PM"
            },
            {
              "id": "443",
              "country": "Russia",
              "address": "qwd qwd qwdqw",
              "date": "Dec 17, 1965, 9:45:17 PM"
            },
            {
              "id": "123",
              "country": "Canada",
              "address": "ktktkt",
              "date": "Dec 17, 1925, 9:45:17 PM"
            }
          ]
          
          const result = Object.values(array.reduce((map, item) => {
          
              map[item.id] = (map[item.id] || []).concat([item]);
          
              return map;
          
            }, {}))
            .filter(item => item.length === 1)
            .map(([item]) => item)
          
          console.log(result)

          【讨论】:

            【解决方案8】:

            使用Array.reduce() 通过 id 构建一个中间字典,其值是具有该 id 的所有项目。然后用Object.values()枚举这个字典的值,用Array.filter()过滤掉包含多个元素的条目,然后用Array.flat()将结果展平:

            const array = [{
                "id": "123",
                "country": "Brazil",
                "address": "xyz abc",
                "date": "Dec 17, 1995, 9:45:17 PM"
              },
              {
                "id": "443",
                "country": "Russia",
                "address": "qwd qwd qwdqw",
                "date": "Dec 17, 1965, 9:45:17 PM"
              },
              {
                "id": "123",
                "country": "Canada",
                "address": "ktktkt",
                "date": "Dec 17, 1925, 9:45:17 PM"
              },
            ];
            
            const singles = Object.values(array.reduce((acc, x) => {
              acc[x.id] = [...(acc[x.id] || []), x];
              return acc;
            }, {})).filter(x => x.length === 1).flat();
            
            console.log(singles);

            【讨论】:

              猜你喜欢
              • 2016-12-01
              • 1970-01-01
              • 2019-01-26
              • 1970-01-01
              • 2021-04-02
              • 2017-08-17
              • 2019-12-08
              • 2011-06-04
              • 2018-09-01
              相关资源
              最近更新 更多