1

For example we have an array

const nums = [1,1,8,12,2,3,3,3,7];

If I want to map number of occurrences of each array member I could use something like

function extractDupes(arr) {
  return arr.reduce(function (acc, item) { 
    if (item in acc) {
      acc[item]++
    }
    else {
      acc[item] = 1
    }
    return acc
  }, {})
}

This would return object like

{ '1': 2, '2': 1, '3': 3, '7': 1, '8': 1, '12': 1 }

Is there an optimal way to filter out numbers which are showing up more than once just with using reduce (in a single pass) and have just

{ '1': 2, '3': 3 }
3
  • I would sort the array and compare values. I have this solved somewhere, let me see if I can find it Commented Sep 3, 2020 at 17:39
  • have a staging variable for values equaling 1 and promote them to the main result when they're hit the second time? Commented Sep 3, 2020 at 17:39
  • I think the resulting code you choose to use should depend on the size of your inputs. :D Commented Sep 3, 2020 at 18:02

6 Answers 6

2

const nums = [1,1,8,12,2,3,3,3,7];
const dups = {};
nums.forEach((v, i, s) => {
  if (s.indexOf(v) != i)
    if (dups[v])
      dups[v]++;
    else
      dups[v] = 2;
});

console.log(dups);

If you also want the array of unique values at the end:

const nums = [1,1,8,12,2,3,3,3,7];
const dups = {};
const uniques = nums.filter((v, i, s) => {
  if (s.indexOf(v) != i)
    if (dups[v])
      dups[v]++;
    else
      dups[v] = 2;
  else
    return true;
});

console.log(dups);
console.log(uniques);

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

2 Comments

I think OP specifically asked for the solution to the problem with reduce method.
@Yousaf Yes, but I think their main concern was with the "in a single pass" part. reduce would actually aggregate no value to this solution because the final object already exists since the very first loop. What we do is just change their content.
1

have a staging variable for values equaling 1 and promote them to the main result when they're hit the second time?

const nums = [1,1,8,12,2,3,3,3,7];

function extractDupes(arr) {
  const staging = {}
  return arr.reduce(function (acc, item) { 
    if (item in acc) {
      acc[item]++
    } else if(item in staging) {
      acc[item] = 2
      delete staging[item]
    } else {
      staging[item] = 1
    }
    return acc
  }, {})
}

document.getElementById('hi').innerHTML = JSON.stringify(extractDupes(nums))
<div id="hi"></div>

Comments

1

You could take a nested property for the final object.

function extractDupes(array) {
    return array
        .reduce(function(acc, item) {
            if (acc[item]) acc.dupes[item] = (acc.dupes[item] || 1) + 1;
            else acc[item] = true;
            return acc;
         }, { dupes: {} })
        .dupes;
}

const nums = [1, 1, 8, 12, 2, 3, 3, 3, 7];

console.log(extractDupes(nums))

Comments

0

You could use Object.entries to transform the object to key-value pairs then filter the pair that have value greater than 1, and then transform the pairs back to object by Object.fromEntries

const nums = [1, 1, 8, 12, 2, 3, 3, 3, 7]

function extractDupes(arr) {
  return Object.fromEntries(
    Object.entries(
      arr.reduce(function (acc, item) {
        if (item in acc) {
          acc[item]++
        } else {
          acc[item] = 1
        }
        return acc
      }, {})
    ).filter(([key, value]) => value > 1)
  )
}

console.log(extractDupes(nums))

Comments

0
let arrAssist = [];

array.sort();
arrAssist.push(inventory[0]);
for(var i = 1; i < array.length; i++){
  if(array[i] != array[i - 1]){
    arrAssist.push(array[i]);
  }
}

in this example, arrAssist contains the array with no duplicates

Comments

0

It has been answered and accepted but anyhow here is how i would do.

const nums = [1, 1, 8, 12, 2, 3, 3, 3, 7];

const map = nums.reduce((acc, num) => {
  acc.frequency[num] = (acc.frequency[num] || 0) + 1;

  if (acc.frequency[num] > 1) {
    acc.replicates[num] = acc.frequency[num];
  }

  return acc;
}, { frequency: {}, replicates: {} });

console.log(map);

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.