0

Say I have an array:

arr = [25, 25, 25, 20, 15, 10, 10, 5];

and I want to count up the number of duplicates (ie. three 25s and 2 10s) and make a new array that becomes:

newArr = ['25 * 3', 20, 15, '10 * 2', 5];

How should I go about doing this? Thanks!

Duncan Law
  • 79
  • 2
  • 9

3 Answers3

2

It can be solved using Set and filter

let arr = [25, 25, 25, 20, 15, 10, 10, 5];

const newArr = [...new Set(arr)].map((x) => {
    const count = arr.filter(y => y == x).length
    return count > 1 ? x + " * " + count: x;
})

console.log(newArr) //  ["25 * 3", 20, 15, "10 * 2", 5]

or if you want the numeric value you can do that

let arr = [25, 25, 25, 20, 15, 10, 10, 5];
    const newArr = [...new Set(arr)].map((x) => arr.filter(y => y == x).length * x)
    console.log(newArr) // [75, 20, 15, 20, 5]
0

You could use reduce and check if the current element in the iteration is equal to the previous element and then also what is the type of last element added to the accumulator.

const arr = [25, 25, 25, 20, 15, 10, 10, 5];
const result = arr.reduce((r, e, i, arr) => {
  if (i && e === arr[i - 1]) {
    if (typeof r[r.length - 1] === 'number') {
      r[r.length - 1] = `${e} * 2`;
    } else {
      const [key, value] = r[r.length - 1].split(' * ')
      r[r.length - 1] = `${key} * ${+value + 1}`
    }
  } else {
    r.push(e)
  }

  return r;
}, [])

console.log(result)
Nenad Vracar
  • 118,580
  • 15
  • 151
  • 176
0

You can use a Array#forEach loop to iterate through each item of the array, keeping track of how many times each item has been seen before.

Demo:

let arr = [25, 25, 25, 20, 15, 10, 10, 5];

let result = [], seenBefore = [];

arr.forEach((item) => {
  let seen = seenBefore.indexOf(item);
  if (seen !== -1) return result[seen].count++;
  result.push({ name: item, count: 1 });
  seenBefore.push(item);
});

result = result.map(({ name, count }) =>
  count > 1 ? `${name} * ${count}` : name
);

console.log(result);

The same technique but smaller using Array#reduce:

let arr = [25, 25, 25, 20, 15, 10, 10, 5];

let result = arr
  .reduce(
    (acc, item) => {
      acc[1].indexOf(item) !== -1 ? acc[0][acc[1].indexOf(item)].count++ : (acc[0].push({ name: item, count: 1 }), acc[1].push(item));
      return acc;
    },
    [[], []]
  )[0]
  .map(({ name, count }) => (count > 1 ? `${name} * ${count}` : name));

console.log(result);
lejlun
  • 4,140
  • 2
  • 15
  • 31