1

I have an array of object and each object is for example :

const myArr=[{name:"john",id:1}{name:"john",id:2}{name:"mary",id:3}]

for the first 2 element for the property "name" I have the name "john" that is duplicate. How can I modify the rendered names like that:

const myArr=[{name:"john (1 of 2)",id:1}{name:"john (2 of 2)",id:2}{name:"mary",id:3}]

Thanks in advance!

4 Answers 4

1

Reduce the input array into a map by name (i.e. group by name property), and map the array of values to the result array. If the group array has more than 1 element in it then sub-map the group to include the numbering. Flatten the overall result.

const myArr = [
  { name: "john", id: 1 },
  { name: "john", id: 2 },
  { name: "mary", id: 3 }
];

const res = Object.values(
  myArr.reduce((groups, current) => {
    if (!groups[current.name]) {
      groups[current.name] = [];
    }
    groups[current.name].push(current);
    return groups;
  }, {})
).flatMap((value) => {
  if (value.length > 1) {
    return value.map((current, i, arr) => ({
      ...current,
      name: `${current.name} (${i + 1} of ${arr.length})`
    }));
  }
  return value;
});

console.log(res);

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

Comments

1

You can do use reduce(), filter(), and flat() and do this:

const myArr = [
  {name:"john", id:1},
  {name:"john", id:2},
  {name:"mary", id:3}
]

const res = Object.values(myArr.reduce((acc, curr) => {
  const total = myArr.filter(({ name }) => name === curr.name).length;

  if(!acc[curr.name]) {
    acc[curr.name] = [
     {...curr}
    ]
  } else {
    const currentSize = acc[curr.name].length;

    if(currentSize === 1) {
      acc[curr.name][0].name = `${acc[curr.name][0].name} (1 of ${total})`
    }
    
    acc[curr.name].push({
      ...curr,
      name: `${curr.name} (${currentSize + 1} of ${total})`
    })    
  }

  return acc;
}, {})).flat();

console.log(res);

Comments

1

const myArr = [{name:"john",id:1}, {name:"john",id:2}, {name:"mary",id:3}];

const namesArray = myArr.map(elem => elem.name);
const namesTraversed = [];
let currentCountOfName = 1;
let len = 0;

myArr.forEach(elem => {
  len = namesArray.filter(name => name === elem.name).length;
  if (len > 1) {
    if (namesTraversed.includes(elem.name)) {
      namesTraversed.push(elem.name);
      currentCountOfName = namesTraversed.filter(name => name === elem.name).length;
      elem.name = `${elem.name} (${currentCountOfName} of ${len})`;
    } else {
      namesTraversed.push(elem.name);
      currentCountOfName = 1;
      elem.name = `${elem.name} (${currentCountOfName} of ${len})`;
    } 
  }
});

console.log(myArr);

Comments

0

Check if this helps you

const myArr = [{
  name: "john",
  id: 1
}, {
  name: "john",
  id: 2
}, {
  name: "mary",
  id: 3
}]

// to keep a track of current copy index
let nameHash = {}

const newMyArr = myArr.map(ele => {
    const noOccurence = myArr.filter(obj => obj.name ===ele.name).length;
    if(noOccurence > 1){
  // if there are multiple occurences get the current index. If undefined take 1 as first copy index.
    let currentIndex = nameHash[ele.name] || 1;
    const newObj =  {
    name: `${ele.name} (${currentIndex} of ${noOccurence})`,
    id: ele.id
    }
    nameHash[ele.name] = currentIndex+ 1;
    return newObj;
  }
  return ele;
})

console.log(newMyArr);

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.