【问题标题】:Trying to set an array with unique values using filter is failing尝试使用过滤器设置具有唯一值的数组失败
【发布时间】:2021-06-27 02:53:34
【问题描述】:

我正在尝试合并 2 个数组,这些数组可能包含一些不同的键,从一个数组到另一个数组。

问题是它没有按应有的方式过滤已经合并的数组。我需要它具有独特的价值。

这是两个数组:

const arr1 = [
  {
    id: "1",
    title: "My Name"
  },
  {
    id: "2",
    title: "Your Name"
  },
  {
    group: [
      {
        id: "4",
        title: "Some Agreement"
      },
      {
        id: "5",
        title: "Some Beer"
      }
    ]
  }
];

const arr2 = [
  {
    id: "1",
    title: "Company Name",
  },
  {
    id: "2",
    title: "A title",
  },
  {
    id: "3",
    title: "Question Group 1",
  },
  {
    id: "4",
    title: "Confidentiality Agreement",
  },
  {
    id: "5",
    title: "Some more",
  },
  {
    id: "6",
    title: "Ayo",
  }
];

第一个数组有时可能包含名为 group 的键,它是与核心数组 ({ id: string, title: string }) 中的对象具有相同类型的 2 个或更多项的混合。

第一个数组符合第二个数组中的项目。

现在我需要将 arr2 的所有项目发送到 arr1 而不从 arr2 中删除这些项目,但我需要从合并中排除现有的项目/ID,它们也必须针对group 键/数组中的项目进行测试。你明白了吗?

这应该是arr1的最终结果:

const arr1 = [
  {
    id: "1",
    title: "My Name"
  },
  {
    id: "2",
    title: "Your Name"
  },
  {
    group: [
      {
        id: "4",
        title: "Some Agreement"
      },
      {
        id: "5",
        title: "Some Beer"
      }
    ]
  },
  {
    id: "3",
    title: "Question Group 1",
  },
  {
    id: "6",
    title: "Ayo",
  }
]

如您所见,新项目必须添加到数组的末尾,该位置应保持不变。

我创建了一个可重现的示例:https://codesandbox.io/s/determined-beaver-r5t6v?file=/src/App.js

以及相关的代码:

  const handleClick = () => {
    setMerge((qs) => {
      const merged = [...qs, ...qs2];

      const unique = merged.filter((v, i, a) => {
        return v.id === a[i].id;
      });

      return unique;
    });
  };

我到达那里是因为我什至无法根据数组的 id 通过唯一值过滤数组。

问题是这个功能可以开发不同的。我只需要不允许 arr2 中的重复项,包括 group 数组中的项。

【问题讨论】:

    标签: javascript arrays reactjs ecmascript-6


    【解决方案1】:

    基本上,您似乎希望将第一个数组的所有内容复制到一个结果数组中,第二个数组中没有匹配的id在第一个。

    此解决方案利用对 group 属性数组的递归搜索,以及仅检查 id 属性的递归基本情况。

    const isContained = (arr, element) => arr.some(el => {
      if (el.group) {
        return isContained(el.group, element); // <-- recurse on group array
      }
      return el.id === element.id // <-- return ids match
    });
    
    ...
    
    const handleClick = () => {
      setMerge((qs) => {
        const merged = [
          ...qs, // <-- shallow copy first array
          ...qs2.filter((el) => !isContained(qs, el)), // <-- filtered second array
        ];
    
        return merged;
      });
    };
    

    【讨论】:

      【解决方案2】:

      以下是实现所需输出的方法之一。

      • 首先使用 arr1 中的 ids 创建一个地图
      • 过滤arr2,其中在步骤1中创建的ids映射中不存在的对象的ID
      • 在步骤 2 中连接 arr1filtered 数组

      const arr1 = [{id:"1",title:"My Name"},{id:"2",title:"Your Name"},{group:[{id:"4",title:"Some Agreement"},{id:"5",title:"Some Beer"}]}];
      
      const arr2 = [{id:"1",title:"Company Name"},{id:"2",title:"A title"},{id:"3",title:"Question Group 1"},{id:"4",title:"Confidentiality Agreement"},{id:"5",title:"Some more"},{id:"6",title:"Ayo"}];
      
      //Create a Map with ids which are present in arr1
      const ids = arr1.reduce((res, obj) => {
        if(obj.group) {
          obj.group.forEach(innerObj => {
            res[innerObj.id] = innerObj
          });
        } else {
          res[obj.id] = obj;
        }
        return res;
      }, {});
      //console.log(ids);
      
      //Filter out the arr2 where the id of an object is not
      //present in the Map created above(i.e., ids object)
      const filteredItems = arr2.filter(({id}) => !ids[id]);
      //console.log(filteredItems);
      
      //Concatenate arr1 and the filteredItems to get the final output
      const finalRes = [...arr1, ...filteredItems];
      console.log(finalRes);
      .as-console-wrapper {
        max-height: 100% !important;
      }

      【讨论】:

        【解决方案3】:

        您可以创建一个Set 来跟踪来自arr1 的现有ID,并且只添加来自arr2 且在arr1 中不存在的项目。

        setMerge((qs) => {
          const ids = new Set()
          qs.forEach((item) => {
            if (item.group) {
              item.group.forEach((el) => ids.add(el.id))
              return
            }
            ids.add(item.id)
          })
        
          const itemsToAdd = qs2.filter((item) => !ids.has(item.id))
          return [...qs, ...itemsToAdd]
        })
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-11-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-09-08
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多