【问题标题】:ReactJs Redux: how to remove duplicate objects (with duplicate values) from an array when deciding redux state (after map, filter, etc. functions)?ReactJs Redux:在决定 redux 状态时(在 map、filter 等函数之后)如何从数组中删除重复的对象(具有重复值)?
【发布时间】:2021-06-14 19:21:18
【问题描述】:

所以我拥有的是一个名为“siteRows”的对象数组。这是在我的减速器中保持的状态。我有一个删除函数,可以“删除”(设置为空)这些行中对象的属性。

例如('-' 符号只是意味着该列没有值,所以为空)

“1 2 3 4 -” “测试我stackoverflow - -” “1 2 3 78 -”

在第 1 行和第 3 行中,“1 2 3”部分是相同的。图像现在您从第一行中删除“4”。那么“1 2 3 - -”是该集合中的“唯一”行。如果我从第三行中删除“78”,您将得到以下信息:

“1 2 3 - -” “测试我stackoverflow - -” “1 2 3 - -”

如您所见,第 0 行和第 2 行(索引)是相同的,不是唯一的,所以我只需要保留 1 行(例如您来的第一行)并且可以删除其余的重复项。如果我删除“78”,我想要以下内容:

“1 2 3 - -” “测试我 stackoverflow - -”

这就是整个数组。

现在,我的代码如下:

      return {
        ...state,
        siteRows: state.siteRows
          .map(recurCheck(action.payload?.id))
          .filter((row) => keys.some(([key]) => row[key]))
          //.splice(state.siteRows.findIndex((row) => row.id))
      };

“recurCheck”基本上循环所有行并删除与正确行关联的正确列。所以这就像“我需要删除第 2 列但第 2 行”然后它会循环第 1 行...没有什么,循环 2...啊是的第 2 列! (设置值=> null),继续等等......

基本上,在那个结果上(所以在“map”和“filter”之后),我也想删除重复项。我不能做“distinct”,因为它是关于对象的,它们有不同的引用,即使是相同的值,所以它永远不会起作用。

现在有没有人可以轻松过滤掉这个数组中的“重复”对象(如果有的话)?所以保留第一个“1 2 3 - -”,但删除其余行(因为它们不是唯一的)?

如您所见,我也尝试过使用“拼接”,也尝试在“过滤器”中添加其他条件,但无济于事。

【问题讨论】:

    标签: javascript reactjs redux rxjs state


    【解决方案1】:

    如果你有一个功能

    const rowsAreEqual = (a, b) => /* returns true if a == b */
    

    那么这个想法很简单:

    function removeDuplicates(array) {
      return array
        .filter((v, i) =>
          array.slice(0, i)
            .every(other => !rowsAreEqual(v, other)
        )
    }
    

    但是,这对于大型数组可能存在效率问题,因为它是 O(n^2)。如果你有办法将每一行序列化为一个基元(即数字或字符串),那么你可以将其设为 O(n):

    const serializeRow = (row) => /* ... return unique number or string for that row */
    
    function removeDuplicates(array) {
      const previousRows = new Set();
      return array
        .filter(v => {
          const id = serializeRow(v);
          if (previousRows.has(id)) {
            return false;
          }
          previousRows.add(id);
          return true;
        })
    }
    

    (如果您愿意,请随意删除 array.filter 并使用普通的旧循环,这只是描述了这个想法)

    如果每一行都只是 number | null 那么类似

    const serializeRow = (row) => row.join(';')
    

    应该够了

    【讨论】:

    • 感谢您的评论!第一次迭代就像一个魅力,谢谢!您认为第一次迭代在什么时候会明显变慢(1-2 秒)? 1000 行?另外,是的,我可以在技术上将行序列化,每行一行,在一个由“;”分隔的字符串中然后检查字符串。我现在将尝试性能更高的解决方案
    • 您的高性能解决方案也有效!我不得不使用 JSON.stringify({param1: obj.param1 etc...} 将其序列化为一个确切的字符串,然后将这些字符串相互检查。无论如何,再次感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 2021-10-31
    • 1970-01-01
    • 2021-04-21
    • 2020-11-29
    • 1970-01-01
    • 2016-10-26
    • 1970-01-01
    • 2021-01-24
    相关资源
    最近更新 更多