0

I have this code:

let peopleInRoom = [];
  for (let message of messages) {
    for (let email of message.user.email) {
      if (!peopleInRoom.includes(email)) {
        peopleInRoom.push(email);
      }
    }
  }

  let peopleInRoomElement = peopleInRoom.map(person => (
    <li>{person}</li>
  ))

Basically I am trying to get all the unique emails and display them.

Is there a shorter and more efficient way (maybe some ES6 features) to write the same code? Seems too much code than needed.

I looked at this answer: How to get distinct values from an array of objects in JavaScript?

EDIT: Above code does not do what I want.

My data looks like this:

[
   {
     text: 'foo',
     user: { email: 'foo@bar.com', password: 'foo' }
   },
   {
     text: 'baz',
     user: { email: 'baz@qux.com', password: 'baz' }
   }
]

The objects are all messages. And I want to get an array of all the unique emails from each message

  • Did you try a Set? – dpwr Nov 16 '20 at 20:27
  • Hi there, welcome to SO! The answer that you have found is definitely the way to go if you want a one-liner, it would work in your case with only a minor modification. If it does not work - are you sure you understand how it's supposed to work? If not, then perhaps your current attempt is better, only you are not processing your data correctly - `message.user.email` is a string, not an array. – Avius Nov 16 '20 at 21:09

5 Answers5

0

If I understand correctly, people have messages, messages have email addresses and the OP seeks the unique set of email addresses. If that's all the data available, then there's no alternative but to iterate it, checking to see if each email has been collected already, and collecting it if it hasn't been.

There are ways to conceal this work by doing it in library code. Probably the highest level utility is lodash's _.uniqueBy, but the work must be done one way or another.

danh
  • 62,181
  • 10
  • 95
  • 136
0

The Set object enforces uniqueness of its elements. You can use it this way:

const peopleInRoom = Array.from(new Set(messages.map(message => message.user.email)));
Louis Coulet
  • 3,663
  • 1
  • 21
  • 39
0

First you can make an array of all the email addresses:

const data = [
   {
     text: 'foo',
     user: { email: 'foo@bar.com', password: 'foo' }
   },
   {
     text: 'baz',
     user: { email: 'baz@qux.com', password: 'baz' }
   }
]

const emailArray = data.map((elem) => {
  return elem.user.email;
}

and then you can filter them to be unique:

function onlyUnique(value, index, self) {
  return self.indexOf(value) === index;
}


emailArrayFiltered = emailArray.filter(onlyUnique);

see here for ref link

Huw
  • 289
  • 2
  • 4
0

You can use the Set object that is built into JavaScript. Set object actually keep the distinct primitive values.

const messages = [
   {
     text: 'foo',
     user: { email: 'foo@bar.com', password: 'foo' }
   },
   {
     text: 'baz',
     user: { email: 'baz@qux.com', password: 'baz' }
   }
]

const peopleInRoom = [...new Set(messages.map(message => message.user.email))];

It actually extracts the email from each message and then passes it to the Set object which only keeps the unique set of emails. After that, it will spread that Set to the array, since Set is also an iterable and returns the array of the people in room.

smtaha512
  • 420
  • 5
  • 11
0

What about:

const peopleInRoom = messages.map(e => e.user.email && e.user.email);
console.log(peopleInRoom)

gives you this output:

["foo@bar.com", "baz@qux.com"]
Patrik
  • 499
  • 1
  • 7
  • 24