Сегодня повторение длинных списков точек данных для поиска уникальной стало обычной операцией бизнес-логики. Подумайте о приложении с полным стеком, таком как CRM (управление ресурсами клиентов) или аналитическом приложении, ориентированном на фильтрацию и предоставление информации о данных о продажах. Вы также можете подумать о более близком примере, таком как функции фильтрации в Microsoft Excel. Если вам когда-либо приходилось анализировать или сравнивать структурированные данные, вы, вероятно, уже использовали функцию «Фильтр уникальных значений» или «Фильтр дубликатов». Хотя Excel, возможно, не является нашим типичным приложением JavaScript, он, по крайней мере, показывает, насколько мощными могут оказаться подобные функции фильтрации для вашего следующего приложения.

Если вам нужна дополнительная мотивация для изучения функций фильтрации, будьте уверены, что это распространенный вопрос на собеседовании по JS. Итак, давайте погрузимся прямо в то, как мы могли бы подойти к такой проблеме. Есть несколько более быстрых способов приблизиться к этому, но в этой статье мы сосредоточимся на том, как мы можем использовать объекты JS для поиска уникального значения в наборе данных. Если вы ищете полное решение, прокрутите вниз.

Теперь давайте разберем это. Сначала рассмотрим следующий массив:

const data =[1,2,4,5,6,6,7,0,8,9,7,9,9,2,0,1,5,6,7,2,9,3,11,11,12]

Кстати, в этом массиве уникальное число — 3, если вы его не заметили. Затем в нашей функции фильтрации нам нужно создать новый пустой объект с помощью инициализатора объекта:

const findSingle = (arr) => {
  let obj = {}
}

Сделав это, мы теперь можем запрограммировать логику нашего алгоритма. Мы начнем перебирать каждое число в массиве чисел, используя цикл for..of:

const findSingle = (arr) => {
  let obj = {}
  for(let item of arr ){
  }
}

Для каждого элемента мы проверим наш недавно созданный объект и сделаем следующее:

a) Мы добавим элемент (т. е. число из массива, который мы сейчас итерируем) в качестве ключа в нашем объекте, используя нотацию obj[name of key] . b) Мы также установим для его value значение +=1, чтобы оно увеличивалось каждый раз, когда мы снова видим одно и то же число при переборе массива.

const findSingle = (arr) => {
  let obj = {}
  for(let item of arr ){
    obj[item]+= 1
  }
}

c) Мы заключаем эту логику в оператор if, чтобы проверитьне был ли уже создан ключ в нашем объекте . Это может показаться противоречащим здравому смыслу, поскольку изначально наш объект не содержит никаких ключей, но, поверьте мне, это сделано намеренно. По сути, мы говорим здесь о том, что шаг a будет реализован только тогда, когда мы увидим один и тот же ключ более одного раза. Теперь это означает, что нампо-прежнему нужно добавлять каждый элемент в качестве ключа в объект по мере выполнения итерации.

const findSingle = (arr) => {
  let obj = {}
  for(let item of arr ){
    if(obj[item]{
      obj[item]+= 1
    }
  }
}

d)Не волнуйтесь, мы можем сделать это внутри блока else нашего оператора if, как показано ниже. Мы говорим здесь о том, что если мы не видели этот конкретный ключ раньше, когда мы перебираем массив, мы установим этот элемент как ключ в объекте с начальным значением из 1:

const findSingle = (arr) => {
  let obj = {}
  for(let item of arr ){
      if(obj[item]{
        obj[item]+= 1
      }else{
        obj[item] = 1
      }
  }
}

Когда мы перебираем массив, каждое число в нашем массиве вставляется в наш объект как уникальный ключ. Благодаря оператору if каждый раз, когда мы видим одно и то же число в массиве, мы не создаем дубликат ключа, а вместо этого просто увеличиваем связанное с ним значение на 1. Вы можете проверить это во время работы, зарегистрировав записи в объекте с помощью Object.entries(obj). Это зарегистрирует все пары ключ-значение, созданные и обновленные в объекте по мере выполнения итерации:

for(let item of arr ){
  console.log(Object.entries(obj);
  ...
}
// log output:
[ [ ‘1’, 1 ], [ ‘2’, 1 ] ]
[ [ ‘1’, 1 ], [ ‘2’, 1 ], [ ‘4’, 1 ] ]
[ [ ‘1’, 1 ], [ ‘2’, 1 ], [ ‘4’, 1 ], [ ‘5’, 1 ] ]
[ [ ‘1’, 1 ], [ ‘2’, 1 ], [ ‘4’, 1 ], [ ‘5’, 1 ], [ ‘6’, 1 ] ]
[ [ ‘1’, 1 ], [ ‘2’, 1 ], [ ‘4’, 1 ], [ ‘5’, 1 ], [ ‘6’, 2 ] ]
...
// notice how as soon as we see 6 another time, the value of key '6' is incremented to 2. 

Таким образом, к концу цикла все, что нам нужно сделать, это проверить ключ в нашем объекте с значением 1. Что делать Теперь мы будем перебирать сам объект, используя цикл for…in вместо цикла for…of, который мы использовали ранее. В то время как цикл for-of выполняет итерацию по любому обычно "итерируемому" объекту, такому как массив чисел, цикл for-in вместо этого будет перебирать свойства, которые'key-ed'например, пары ключ-значение в нашем объекте:

for(let item in obj){
  if(obj[item] === 1){ 
    return item
  }
}

Наконец, давайте соберем все вместе: