Reputation: 89
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]));
Upvotes: 4
Views: 22263
Reputation: 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]
Upvotes: 0
Reputation: 934
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;
Upvotes: 0
Reputation: 41
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);
Upvotes: 4
Reputation: 81
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)
Upvotes: 2
Reputation: 147413
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]));
Upvotes: 5
Reputation: 104379
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.
Upvotes: 3
Reputation: 3822
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);
Upvotes: 8