【问题标题】:How to remove duplicates from array of objects and combine values of that duplicates?如何从对象数组中删除重复项并组合该重复项的值?
【发布时间】:2022-01-24 21:48:28
【问题描述】:

我有这样的数组,我的 idname 对于多个对象将是相同的,但 organizations 的值可以不同

array= [
  {id: 1, name: "Test1", organizations: 1},
  {id: 1, name: "Test1", organizations: 2},
  {id: 1, name: "Test1", organizations: 3},
  {id: 2, name: "Test2", organizations: 4},
  {id: 2, name: "Test2", organizations: 5},
  {id: 2, name: "Test2", organizations: 6} 
];

我想把它变成这样:

expectedArray =  [
  {id: 1, name: "Test1", organizations: [1,2,3]},
  {id: 2, name: "Test2", organizations: [4,5,6]} 
];

有人可以帮忙

【问题讨论】:

标签: javascript arrays reactjs react-native


【解决方案1】:

const array= [
  {id: 1, name: "Test1", organizations: 1},
  {id: 1, name: "Test1", organizations: 2},
  {id: 1, name: "Test1", organizations: 3},
  {id: 2, name: "Test2", organizations: 4},
  {id: 2, name: "Test2", organizations: 5},
  {id: 2, name: "Test2", organizations: 6} 
];

const mergeDuplicates= (field, uniqueField) => (source = [], value)=> {
    const target = source.find( item => item[uniqueField] == value[uniqueField] );
    if(target) target[field].push( value[field] );
    else source.push({...value, [field]: [ value[field] ] });
    return source;
}
const mergeOrganaizationsById = mergeDuplicates('organizations','id')
const result = array.reduce(mergeOrganaizationsById, [])
console.log(result)

【讨论】:

    【解决方案2】:

    你会想要减少。

    array.reduce((acc, cur) => {
      const i = acc.findIndex(a => a.id === cur.id && a.name === cur.name);
      if (i === -1) return [...acc, {...cur, organizations: [cur.organizations]}];
      return [...acc.slice(0, i), {...cur, organizations: [...acc[i].organizations, cur.organizations]}, ...acc.slice(i +1)];
    }, []);
    

    【讨论】:

      【解决方案3】:

      您可以使用forEach 实现输出,方法是基于name 进行分组,然后将必要的字段推入输出数组。

      const array = [
        { id: 1, name: "Test1", organizations: 1 },
        { id: 1, name: "Test1", organizations: 2 },
        { id: 1, name: "Test1", organizations: 3 },
        { id: 2, name: "Test2", organizations: 4 },
        { id: 2, name: "Test2", organizations: 5 },
        { id: 2, name: "Test2", organizations: 6 }
      ];
      
      const current = Object.create(null);
      const finalArr = [];
      array.forEach(function (o) {
        if (!current[o.name]) {
         current[o.name] = [];
         finalArr.push({ id: o.id, name: o.name, organizations: current[o.name] });
        }
        current[o.name].push(o.organizations);
      });
      console.log(finalArr);
      .as-console-wrapper { max-height: 100% !important; top: 0; }

      【讨论】:

        【解决方案4】:

        ES6 风格的另一种解决方案

        const array= [{id: 1, name: "Test1", organizations: 1},{id: 1, name: "Test1", organizations: 2},{id: 1, name: "Test1", organizations: 3},{id: 2, name: "Test2", organizations: 4},{id: 2, name: "Test2", organizations: 5},{id: 2, name: "Test2", organizations: 6}];
        
        const result =  Object.values(array.reduce((acc, { id, name, organizations }) => {
          const hash = `${id}-${name}`;
          acc[hash] = acc[hash] 
            ? { ...acc[hash], organizations: [...acc[hash].organizations, organizations] } 
            : { id, name, organizations: [organizations] };
          return acc;
        }, {}));
        
        console.log(result);
        .as-console-wrapper { max-height: 100% !important; top: 0; }

        【讨论】:

        • 我最喜欢这个解决方案。您唯一需要注意的是哈希构造,如果任一字段中有破折号,您最终可能会得到错误匹配。
        【解决方案5】:

        我认为这可能是解决这个问题的最简单方法,只使用 forEach 和基本数组的方法。

        希望我回答了你的问题。

        const array = [
          { id: 1, name: "Test1", organizations: 1 },
          { id: 1, name: "Test1", organizations: 2 },
          { id: 1, name: "Test1", organizations: 3 },
          { id: 2, name: "Test2", organizations: 4 },
          { id: 2, name: "Test2", organizations: 5 },
          { id: 2, name: "Test2", organizations: 6 }
        ];
        
        const newArr = [];
        
        // for keeping track for added item
        const addedItems = [];
        
        // for keeping track of added item idx
        let addedItemIdx = 0;
        
        array.forEach((item) => {
          if (!addedItems.includes(item.id)) {
            let tempOrg = item.organizations;
            newArr.push({ ...item, organizations: [tempOrg] });
            addedItems.push(item.id);
            addedItemIdx++;
          } else {
            newArr[addedItemIdx - 1].organizations.push(item.organizations);
          }
        });
        console.log(newArr);

        【讨论】:

          【解决方案6】:

          您要查找的内容称为哈希图。您可以阅读它们,但基本思想是您制作一个键、值对并使用键访问数据非常有效(O(1) 摊销)。所以这是在python中解决这个问题的一种方法。我相信你可以用它来用你的语言解决它。

              array= [
            {"id": 1, "name": "Test1", "organizations": 1},
            {"id": 1, "name": "Test1", "organizations": 2},
            {"id": 1, "name": "Test1", "organizations": 3},
            {"id": 2, "name": "Test2", "organizations": 4},
            {"id": 2, "name": "Test2", "organizations": 5},
            {"id": 2, "name": "Test2", "organizations": 6}
          ]
          # Initilize a hashmap
          hash_map = {}
          # Loop over all the items in array and create the hashmap
          for item in array:
              # key will be id and name as both are needed to group the organizations
              # We have use comma to separate them as we assume that name or id cannot have comma
              key = str(item["id"])+","+item["name"]
              # IF key is already present then add the new organizations id to it
              if key in hash_map:
                  hash_map[key].append(item["organizations"])
              # Else make a new list with the current organizations id
              else:
                  hash_map[key] = [item["organizations"]]
          
          # Create the expected array
          expected_array = []
          for key,value in hash_map.items():
              # Get the id and name by spliting the key that we created 
              idx,name = key.split(",")
              expected_array.append({"id":idx,"name":name,"organizations":value})
          print(expected_array)
          

          【讨论】:

            【解决方案7】:

            const array = [
              { id: 1, name: "Test1", organizations: 1 },
              { id: 1, name: "Test1", organizations: 2 },
              { id: 1, name: "Test1", organizations: 3 },
              { id: 2, name: "Test2", organizations: 4 },
              { id: 2, name: "Test2", organizations: 5 },
              { id: 2, name: "Test2", organizations: 6 }
            ];
            
            const result=array.reduce((acc,curr)=>{
              const id=curr.id;
              const {organizations}=curr;
               const findIndex=acc.findIndex(item=> item.id===curr.id)
              if(findIndex===-1){
                acc.push({...curr,organizations:[organizations]});
              } else {
               
                acc[findIndex].organizations.push(curr.organizations)
              }
              return acc;
            },[]);
            console.log(result);
            .as-console-wrapper { max-height: 100% !important; top: 0; }

            【讨论】:

              【解决方案8】:

              这应该可以

              const array = [{
                  id: 1,
                  name: "Test1",
                  organizations: 1
                },
                {
                  id: 1,
                  name: "Test1",
                  organizations: 2
                },
                {
                  id: 1,
                  name: "Test1",
                  organizations: 3
                },
                {
                  id: 2,
                  name: "Test2",
                  organizations: 4
                },
                {
                  id: 2,
                  name: "Test2",
                  organizations: 5
                },
                {
                  id: 2,
                  name: "Test2",
                  organizations: 6
                }
              ];
              const reducedArray = array.reduce((resultArray, arrayElement) => {
                const elementIndex = resultArray.findIndex(element => element.id === arrayElement.id);
              
                if (elementIndex !== -1) {
                  resultArray[elementIndex].organizations.push(arrayElement.organizations)
                } else {
                  resultArray.push({
                    ...arrayElement,
                    organizations: [arrayElement.organizations],
                  });
                }
                return resultArray;
              }, []);
              
              console.log(reducedArray)

              【讨论】:

                【解决方案9】:

                const array = [{
                    id: 1,
                    name: "Test1",
                    organizations: 1
                  },
                  {
                    id: 1,
                    name: "Test1",
                    organizations: 2
                  },
                  {
                    id: 1,
                    name: "Test1",
                    organizations: 3
                  },
                  {
                    id: 2,
                    name: "Test2",
                    organizations: 4
                  },
                  {
                    id: 2,
                    name: "Test2",
                    organizations: 5
                  },
                  {
                    id: 2,
                    name: "Test2",
                    organizations: 6
                  }
                ];
                
                
                const formattedData = array.reduce((result, {
                  id,
                  name,
                  organizations
                }) => {
                  let filteredRow = result.find(row => row.id === id && row.name === name);
                  const org = filteredRow ? filteredRow.organizations : [];
                  org.push(organizations);
                  filteredRow = {
                    id,
                    name,
                    organizations: org
                  };
                  if (org.length === 1) result.push(filteredRow);
                  return result;
                }, [])
                
                console.log(formattedData)

                【讨论】:

                • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
                猜你喜欢
                • 2022-12-05
                • 2021-01-23
                • 2017-04-10
                • 1970-01-01
                • 1970-01-01
                • 2011-01-09
                • 2019-02-28
                相关资源
                最近更新 更多