4

I am trying to remove duplicates from a list of arrays. The way I was trying to do this is by using reduce to create an empty array that pushes all undefined indexes onto that array. I am getting errors though that

if(acc[item]===undefined){
      ^
TypeError: Cannot read property '1' of undefined

my function below:

function noDuplicates(arrays) {
  var arrayed = Array.prototype.slice.call(arguments);

  return reduce(arrayed, function(acc, cur) {
    forEach(cur, function(item) {
      if (acc[item] === undefined) {
        acc.push(item);
      }
      return acc;
    });
  }, []);
}

console.log(noDuplicates([1, 2, 2, 4], [1, 1, 4, 5, 6]));

3
  • What should be the output of console.log(noDuplicates([1,2,2,4],[1,1,4,5,6]));? Commented May 4, 2017 at 4:41
  • output should be [1,2,4,5,6] Commented May 4, 2017 at 4:43
  • Possible duplicate of Remove Duplicates from JavaScript Array Commented May 4, 2017 at 5:07

7 Answers 7

8

First concatenate the two arrays, next use filter() to filter out only the unique items-

var a = [1, 2, 2, 4], b = [1, 1, 4, 5, 6];
var c = a.concat(b);
var d = c.filter(function (item, pos) {return c.indexOf(item) == pos});
console.log(d);

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

Comments

5

There are a number of issues with how you're calling methods and where you return acc from:

function noDuplicates(arrays) {
  var arrayed = Array.prototype.slice.call(arguments);

  // reduce is a method of an array, so call it as a method
  // return reduce(arrayed, function(acc, cur) {
  return arrayed.reduce(function(acc, cur) {
  
    // Same with forEach
    cur.forEach(function(item) {
      if (acc[item] === undefined) {
        acc.push(item);
      }
       // Return acc from the reduce callback, forEach returns undefined always
       // return acc;
    });
    return acc;
  }, []);
}

console.log(noDuplicates([1, 2, 2, 4], [1, 1, 4, 5, 6]));

You could also call reduce directly on arguments using call:

Array.prototype.reduce.call(arguments, function(acc, curr) {
  // ...
});

The above makes your code run, but it doesn't produce the correct output as the test:

  if (acc[item] === undefined)

doesn't do what you want. What you need to do is remember each value and only push it to acc if it's not been seen before:

function noDuplicates(arrays) {
  var arrayed = Array.prototype.slice.call(arguments);
  var seen = {};

  return arrayed.reduce(function(acc, cur) {
    cur.forEach(function(item) {
      if (!seen[item]) {
        acc.push(item);
        seen[item] = true;
      }
    });
    return acc;
  }, []);
}

console.log(noDuplicates([1, 2, 2, 4], [1, 1, 4, 5, 6]));

Some other approaches:

// A more concise version of the OP
function noDupes() {
  return [].reduce.call(arguments, function(acc, arr) {
    arr.forEach(function(value) {
      if (acc.indexOf(value) == -1) acc.push(value);
    });
    return acc;
   },[]);
}
 
console.log(noDupes([1, 2, 2, 4], [1, 1, 4, 5, 6]));

// Some ECMAScript 2017 goodness
function noDupes2(...args){
 return [].concat(...args).filter((v, i, arr) => arr.indexOf(v)==i);
}

console.log(noDupes2([1, 2, 2, 4], [1, 1, 4, 5, 6]));

Comments

4

Any reason of using reduce? because we can do this easily by first merging these two arrays then by using Set to remove the duplicate keys.

Check this:

function noDuplicates(a, b){
    var k = a.concat(b);
    return [...new Set(k)];
}

console.log(noDuplicates([1,2,2,4],[1,1,4,5,6]));

Check the DOC, how Set works.

1 Comment

Using the array concatenation kinda diminishes the point of using Set which is a good idea.
4

My Solution is -

var numbers = [1, 1, 2, 3, 4, 4];

function unique(array){
  return array.reduce(function(previous, current) {
     if(!previous.find(function(prevItem){
         return prevItem === current;
     })) {
        previous.push(current);
     }
     return previous;
 }, []);
}

unique(numbers);

Comments

2

looking for a smoother solution for MDN's exact same problem, I've came up with that solution, I find it simple and nice. I have also just updated it in MDN and wanted to share it here (I'm really new to that stuff, so sorry if did something wrong)

let myArray = ['a', 'b', 'a', 'b', 'c', 'e', 'e', 'c', 'd', 'd', 'd', 'd'];
var myOrderedArray = myArray.reduce(function (accumulator, currentValue) {
  if (accumulator.indexOf(currentValue) === -1) {
    accumulator.push(currentValue);
  }
  return accumulator
}, [])

console.log(myOrderedArray);

(I'm really new to this, hope it'd help)

Comments

1

Remove duplicate elements from an array using reduce function in JS

const arr = [1,2,3,4,4,5,5,5,6];

const uniqueArray = (arr) => {
    return arr.reduce((acc,ele) => {
        return acc.includes(ele) ? acc : [...acc,ele]
    },[])
}

console.log(uniqueArray(arr)); // [1,2,3,4,5,6]

Comments

0

The previous answers are not optimized for large arrays. The following allows for linear big O notation:

const dedupWithReduce = (arr) =>
  arr.reduce(
    (acc, cur) => {
      if (!acc.lookupObj[cur]) {
        return {
          lookupObj: {
            ...acc.lookupObj,
            [cur]: true
          },
          dedupedArray: acc.dedupedArray.concat(cur)
        };
      } else {
        return acc;
      }
    },
    { lookupObj: {}, dedupedArray: [] }
  ).dedupedArray;

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.