0

I have this array of objects:

const arrayOfObjects = [{
    id: 10,
    children: [1000]
  },
  {
    id: 10,
    children: [2000]
  },
  {
    id: 20,
    children: [1000]
  },
  {
    id: 20,
    children: [1000, 2000]
  },
  {
    id: 20,
    children: [2000]
  },
];

I want to remove duplicates using this code:

  const arrayHashMap = arrayOfObjects.reduce((obj, item) => {
    if (obj[item.id]) {
      // obj[item.id].children.push(...item.children);
      const temporaryArray = [...obj[item.id].children, ...item.children];
      obj[item.id].children = [...new Set(temporaryArray)];
    } else {
      obj[item.id] = {
        ...item
      };
    }
    return obj;
  }, {});
  const result = Object.values(arrayHashMap);

In this code I commented part where I push values to array. I tried to use "new Set" to remove duplicates from final array, but I am always assigning the value to "obj[item.id].children". Is this OK or is there a better way to write this?

Expected result:

[{
  id: 10,
  children: [1000, 2000]
}, {
  id: 20,
  children: [1000, 2000]
}]

Thanks

2
  • 1
    please add the wanted result. Commented Jun 6, 2021 at 8:30
  • @NinaScholz I added expected result. Commented Jun 6, 2021 at 8:47

7 Answers 7

1

You could group by id and check the array if the value not exists, then push the value.

const
    data = [{ id: 10, children: [1000] }, { id: 10, children: [2000] }, { id: 20, children: [1000] }, { id: 20, children: [1000, 2000] }, { id: 20, children: [2000] }],
    result = Object.values(data.reduce((r, { id, children }) => {
        r[id] ??= { id, children: [] };
        children.forEach(v => {
            if (!r[id].children.includes(v)) r[id].children.push(v);
        })
        return r;
    }, {}));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

Comments

0

Use Array#prototype#reduce to reduce over the array and initialize a set over the children property and keep on adding to the set and lastly map the set back to an array.

const arrayOfObjects = [{
    id: 10,
    children: [1000]
  },
  {
    id: 10,
    children: [2000]
  },
  {
    id: 20,
    children: [1000]
  },
  {
    id: 20,
    children: [1000, 2000]
  },
  {
    id: 20,
    children: [2000]
  },
];

const result = Object.values(
    arrayOfObjects.reduce((r, c) => {
      r[c.id] = r[c.id] || {
        id: c.id,
        children: new Set()
      };

      c.children.forEach((item) => r[c.id].children.add(item));
      return r;
    }, Object.create(null))
  )
  .map((x) => ({
    id: x.id,
    children: [...x.children]
  }));

console.log(result);

Comments

0

const arr = [
  {
    id: 10,
    children: [1000],
  },
  {
    id: 10,
    children: [2000],
  },
  {
    id: 20,
    children: [1000],
  },
  {
    id: 20,
    children: [1000, 2000],
  },
  {
    id: 20,
    children: [2000],
  },
];
let result = arr.reduce((acc, i) => {
  let obj = acc.find((a) => a.id === i.id);
  obj ? (obj.children = [...new Set(obj.children.concat(i.children))]): acc.push(i);
  return acc;
}, []);

console.log(result);

Comments

0

you can try this fiddle : https://jsfiddle.net/d0kboywv/2/

const arrayOfObjects = [
  {
    id: 10,
    children: [1000]
  },
  {
    id: 10,
    children: [2000]
  },
  {
    id: 20,
    children: [1000]
  },
  {
    id: 20,
    children: [1000, 2000, 3000]
  },
  {
    id: 20,
    children: [2000, 4000]
  },
];

let mappedArray = new Map(arrayOfObjects.map(o => [o.id, {}] ));
for (let obj of arrayOfObjects) {
    let child = mappedArray.get(obj.id);
    for (let [key, val] of Object.entries(obj.children)) {
        child[key] = (child[key] || new Set).add(val);
    }
}
let result = Array.from(mappedArray.entries(), ([id, child]) => ({ 
    id, 
    children: [...new Set(Object.entries(child).map(([k, v]) => 
        [...v]
    ).reduce((a, b) => a.concat(b), []))].sort()
}));
console.log(result);

It do the job for me !

Comments

0

you can temporary transform data structure to more simple

const objectOfArray = {}; your id is key, your children is value

I use name initialData for refer to your array

  const objectOfArray = {};
  initialData.forEach(e => {
    if (objectOfArray[e.id] {
      objectOfArray[e.id].push(...e.children);
    } else {
      objectOfArray[e.id] = [...e.children];
    }
  });


  const result = Object.entries(objectOfArray).map(([id, children]) => {
    return {
      id,
      children: children.filter((e, i) => i === chilren.indexOf(i)),
    }
  });

Comments

0

You can also achieve expected output by running the below code

makeMapping = {};
for (let obj of arrayOfObjects) {
    makeMapping[obj.id] = {...obj, children: [...new Set([...obj.children, ...(makeMapping[obj.id]?.children || [])])]};
}
console.log(Object.values(makeMapping));

Comments

0

i dont know about "better", but perhaps terser:

const arrayOfObjects = [{
    id: 10,
    children: [1000]
  },
  {
    id: 10,
    children: [2000]
  },
  {
    id: 20,
    children: [1000]
  },
  {
    id: 20,
    children: [1000, 2000]
  },
  {
    id: 20,
    children: [2000]
  },
];

const arrayHashmap = arrayOfObjects.reduce((obj, {
  id,
  children
}) => ({
  ...obj,
  [id]: {
    id,
    children: [...new Set([
      ...obj[id]?.children ?? [],
      ...children
    ])]
  }
}), {})

const result = Object.values(arrayHashmap);
console.log(result)

edit: whoops, the "tidy" button changed semantics. fixed.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.