0

I want to add items to an array skipping the duplicates. However for some reason only one item is being added and the second item is not being added. Here is my code.

var add = ['email1@gmail.com', 'email2@gmail.com', 'email1@gmail.com'];
var main_messages = []
var from 
function findMessages(messageList) {
  return messageList = from;
}

add.map(function(map){
  from = map
  if(main_messages.find(findMessages) === undefined){
    main_messages.push(map)
  }
});

console.log(main_messages)

So the expected output should be

['email1@gmail.com', 'email2@gmail.com']

But the output I'm getting in this code is only

['email1@gmail.com']

What am I doing wrong and how can I fix this problem?

rksh
  • 3,920
  • 10
  • 49
  • 68
  • just a hint, map returns for every element a return value. if not set, then `undefined`. you may look for filter, which returns the item if a truthy value is returned. – Nina Scholz Nov 10 '16 at 09:52

7 Answers7

2

Consider using the JavaScript 1.6 / ECMAScript 5 native filter method of an Array in the following way:

var add = ['email1@gmail.com', 'email2@gmail.com', 'email1@gmail.com'];
var main_messages = add.filter(function(v, i, a) {return a.indexOf(v) === i;});

Another solution that should offer better performance O(x) would be to use array.reduce:

main_messages = Object.keys(add.reduce(function (p,c) {return (p[c] = true,p);},{}));

Both solutions will result in messages containing:

["email1@gmail.com", "email2@gmail.com"]

In case you need support for Browsers that don't have this implemented, as always there is a pollyfill offered by Mozilla (see bottom of page)

Radu Maris
  • 5,648
  • 4
  • 39
  • 54
2

Looks like you're missing a = in your return statement of findMessages, so you're basically setting from to messageList instead of comparing. Here's the fixed code

var add = ['email1@gmail.com', 'email2@gmail.com', 'email1@gmail.com'];
var main_messages = []
var from 
function findMessages(messageList) {
  return messageList === from;
}

add.map(function(map){
  from = map
  if(main_messages.find(findMessages) === undefined){
    main_messages.push(map)
  }
});

console.log(main_messages)
H77
  • 5,859
  • 2
  • 26
  • 39
1

i think your error in below code

function findMessages(messageList) {
  return messageList = from;
}

here i think you return to its parent so it is showing one vale. for this you need to store messageList = from in a var, then return that variable.

var x = messageList;
return x;
Sangram Badi
  • 4,054
  • 9
  • 45
  • 78
1

You could implement a uniq function. Which is a specialised form of filter.

var add = ['email1@gmail.com', 'email2@gmail.com', 'email1@gmail.com'];
var main_messages = uniq(add);
                               
function uniq(arr) {
 var result = [];
 for (var i = 0; i < arr.length; i++) {
  if (result.indexOf(arr[i]) === -1) {
   result.push(arr[i]);
  }
 }
 return result;
}

console.log(main_messages)

On the other hand, map will always return an array of the same size, unless of course you muck about with assignments, etc.

map passes each element of an array to a callback function you use to modify the individual element without touching the actual array.

Think of it as 1 in 1 out, and so on, but you get the chance to change what is in the array, not how many things are in there. The idea is that there that the array resulting from map has the same length of the input array, but different content.

Methods that can result in an array of different size are filter and reduce for instance.

So being super-terse you could also do this:

var add = ['email1@gmail.com', 'email2@gmail.com', 'email1@gmail.com'];
var main_messages = add.filter( (el, idx, input) => input.indexOf(el) === idx );
console.log(main_messages)
tmslnz
  • 1,801
  • 2
  • 15
  • 24
0

You can use indexOf function in order to check the duplicate. You can try below way to add items to your array without duplicates.

var add = ['email1@gmail.com', 'email2@gmail.com', 'email1@gmail.com'];
var main_messages = []

add.map(function(map){
  if(main_messages.indexOf(map) == -1){
    main_messages.push(map)
  }
});
console.log(main_messages);
Girish Vadhel
  • 735
  • 1
  • 5
  • 17
0

Here is an easy answer: https://stackoverflow.com/a/18328062/5228251

Why do it the hard way, it can be done more easily using javascript filter function which is specifically for this kind of operations:

var add = ['email1@gmail.com', 'email2@gmail.com', 'email1@gmail.com'];
var main_messages = []

main_messages = add.filter( function( item, index, inputArray ) {
           return inputArray.indexOf(item) == index;
    });

------------------------
Output: ['email1@gmail.com', 'email2@gmail.com']
Community
  • 1
  • 1
narainsagar
  • 1,079
  • 2
  • 13
  • 29
0

Depending on your needs, using a Set instead of an array may be what you are looking for:

The Set object lets you store unique values of any type, whether primitive values or object references.

var add = ['email1@gmail.com', 'email1@gmail.com', 'email2@gmail.com', 'email1@gmail.com'];

// Init from an iterable.
var main_messages = new Set(add);

// Add a new email (not previously in the set).
main_messages.add('email3@gmail.com');

// Try to add an existing email, does nothing.
main_messages.add('email1@gmail.com');

console.log('main_messages:')
main_messages.forEach(msg => console.log('-', msg));

Of course, this option is only viable if you keep the data stored in the Set. It would be quite inefficient to convert it into an array after each insertion.

Set is an ES2015 feature. You may want to check the compatibility table and consider using a polyfill if needed.

Quentin Roy
  • 7,677
  • 2
  • 32
  • 50