0

I have a array like this:

let obj = [
    {
        id: 1,
        name: 'bob'
    },
        {
        id: 2,
        name: 'bob'
    },
        {
        id: 3,
        name: 'karl'
    },
        {
        id: 4,
        name: 'joe'
    },
        {
        id: 5,
        name: 'joe'
    },    {
        id: 6,
        name: 'rick'
    },
    
];

I need to write some javascript code to parse through the array and handle the duplicate names.

My desired outcome is:

let obj = [
    {
        id: [1,2],
        name: 'bob'
    },
    {
        id: 3,
        name: 'karl'
    },
        {
        id: [4,5],
        name: 'joe'
    },
    {
        id: 6,
        name: 'rick'
    },
];

Can anyone help?

1
  • Do the non grouped ids need to appear standalone (ie. not in an array)? If they can also be in an array, then this question will answer your question: Group array items using object Commented May 16, 2021 at 1:31

2 Answers 2

2

You can easily achieve this result using reduce and find. If the existing element is an array then you need to push it into array else create an array and push the existing element in the array along with new id

let obj = [
  {
    id: 1,
    name: "bob",
  },
  {
    id: 2,
    name: "bob",
  },
  {
    id: 3,
    name: "karl",
  },
  {
    id: 4,
    name: "joe",
  },
  {
    id: 5,
    name: "joe",
  },
  {
    id: 6,
    name: "rick",
  },
];

const result = obj.reduce((acc, curr) => {
  const { id, name } = curr;
  const findEl = acc.find((o) => o.name === name);
  if (findEl) {
    if (Array.isArray(findEl.id)) {
      findEl.id.push(id);
    } else {
      findEl.id = [findEl.id, id];
    }
  } else {
    acc.push({ id, name });
  }
  return acc;
}, []);

console.log(result);

You can improve its time complexity by introducing a dictionary and no need to find elements every time in reduce. But here order can change of the object inside result

let obj = [
  {
    id: 1,
    name: "bob",
  },
  {
    id: 2,
    name: "bob",
  },
  {
    id: 3,
    name: "karl",
  },
  {
    id: 4,
    name: "joe",
  },
  {
    id: 5,
    name: "joe",
  },
  {
    id: 6,
    name: "rick",
  },
];

const dict = {};
obj.forEach((obj) => {
  const { id, name } = obj;
  if (dict[name]) {
    if (Array.isArray(dict[name])) {
      dict[name].push(id);
    } else {
      dict[name] = [dict[name], id];
    }
  } else {
    dict[name] = id;
  }
});

const result = Object.entries(dict).map(([name, id]) => ({ name, id }));

console.log(result);

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

Comments

0

Array.prototype.reduce() is useful in this case.

let obj = [{
    id: 1,
    name: 'bob'
  },
  {
    id: 2,
    name: 'bob'
  },
  {
    id: 3,
    name: 'karl'
  },
  {
    id: 4,
    name: 'joe'
  },
  {
    id: 5,
    name: 'joe'
  }, {
    id: 6,
    name: 'rick'
  },
];
const mergeObjectByValue = (objArray) => {
  const newObjs = objArray.reduce((prev, {
    name,
    id
  }) => {
    (name in prev) ? prev[name].push(id): prev[name] = [id]
    return prev;
  }, {})
  return Object.entries(newObjs).map(([name, ids]) => ({
    name,
    id: ids.length > 1 ? ids : ids[0],
  }))
}
console.log(mergeObjectByValue(obj))

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.