Как я могу создать отдельный список объектов javascript, когда мне нужен составной ключ, чтобы сделать его отличным? - PullRequest
1 голос
/ 23 мая 2019

Да, есть несколько сообщений о создании отдельных списков на нескольких языках, но я не вижу ничего об использовании составного или составного ключа.

У меня есть массив объектов (контактов) с дубликатами,из которого мне нужно создать массив различных значений, с ключом , составным из полей электронной почты, имени и телефона.Объекты выглядят так:

{
    name: "Name",
    email: "email@example.com",
    phone: "5551212",
    organization: "BigCompany",
    title: "CEO"
}

Я могу создать отдельный список, используя map.has (), основываясь только на электронной почте:

const distinct = [];
const map = new Map();
for (const item of contacts) {
    if(!map.has(item.email)){
        map.set(item.email, true); // set any value, but add an entry to the Map
        distinct.push(item);
    }
}

... но мне нужен отдельный массивэлементы для каждого контакта с одним и тем же адресом электронной почты, но с другим телефоном или тем же телефоном, но с другим адресом электронной почты и т. д. Читая документацию по map.has(), я не вижу ничего о том, что параметр ключа является сложной структурой данных (несколькополя, в данном случае).Есть какой-то лучший инструмент, или я просто пропустил этот раздел документации?

Ответы [ 2 ]

3 голосов
/ 23 мая 2019

Вы можете создать строку JSON для использования в качестве ключа, например:

const distinct = [];
const map = new Map();
for (const item of contacts) {
    const {name, email, phone} = item;
    const key = JSON.stringify({name, email, phone});
    if(!map.has(key){
        map.set(key, true);
        distinct.push(item);
    }
}

Поскольку JSON.stringify ( spec | MDN ) требуется для следования порядку свойств ES2015 (что не выполняется многими операциями), вы знаете, что если вы создаете объекты в каждый раз, когда все перечисляемые свойства являются «собственными» свойствами, результирующая строка JSON будет одинаковой для объектов с одинаковыми значениями свойств name, email и phone (и разными, если они разные). (Важно то, что «каждый раз создавайте объекты одинаково», объекты {a: 1, b: 2} и {b: 2, a: 1} приводят к различным строкам JSON.)


Примечание: если вы просто используете map.has и map.set(key, true), то Set, вероятно, будет иметь больше смысла:

const distinct = [];
const set = new Set();
for (const item of contacts) {
    const {name, email, phone} = item;
    const key = JSON.stringify({name, email, phone});
    if(!set.has(key){
        set.add(key);
        distinct.push(item);
    }
}
0 голосов
/ 23 мая 2019

Вы можете использовать Map для хранения своих отдельных контактов, создав собственный составной ключ:

const contacts = [
  {
    name: "Name",
    email: "email@example.com",
    phone: "5551212",
    organization: "BigCompany",
    title: "CEO"
  },
  // ...
]

// Store distinct contacts.
const map = new Map()

contacts.forEach((c) => {
  /**
   * Any contact with the same name, email, and phone will
   * be considered a duplicate.
   */
  const key = `${c.name}::${c.email}::${c.phone}`
  map.set(key, c)
})

Теперь ваша карта представляет собой контейнер предметов { key => contact }.

Чтобы получить список отдельных контактов, используйте:

const list = Array.from(map.values())

// Use spread syntax to accoplish the same thing.
const list2 = [...map.values()]

Примечание: использование разделителя :: может считаться небезопасным, если имя, адрес электронной почты или номер телефона могут содержать эту подстроку. Какой бы разделитель вы ни использовали, вы должны по возможности запретить его ввод в эти поля и / или сделать так, чтобы вероятность его появления на входе была крайне маловероятной:

const delim = '__:DELIM:__'
const key = `${c.name}${delim}${c.email}${delim}${c.phone}`

Тем не менее, нет 100% гарантии, что разделитель не появится в таком поле, как name, если вы не выполните проверку ввода для этого поля.

РЕДАКТИРОВАТЬ: На экзамене T.J. JSON-ключ Crowder, использование этого метода для генерации вашего ключа обеспечит хорошую гарантию отсутствия проблем с подстрокой:

const key = JSON.stringify({name, email, phone});
map.set(key, c)
...