Получение последних дубликатов / тройных копий из массива

#javascript #arrays #algorithm #reduce

#javascript #массивы #алгоритм #уменьшить

Вопрос:

У меня есть массив, и я хочу знать, какие из них являются дубликатами / тройными или более.

Пример: получение последнего элемента только тогда, когда он отображается 3 или более раз.

Ввод:

 const items = [
  {id: 3, date: new Date('2020/8/3')},
  {id: 1, date: new Date('2020/8/1')},
  {id: 1, date: new Date('2020/8/4')},
  {id: 1, date: new Date('2020/8/2')},
  {id: 2, date: new Date('2020/8/1')},
  {id: 2, date: new Date('2020/8/4')},
  {id: 3, date: new Date('2020/8/3')},
  {id: 3, date: new Date('2020/8/4')},
  {id: 1, date: new Date('2020/8/3')},
]
  

Теперь идентификатор 1 отображается 4 раза, идентификатор 2 — 2 раза, а идентификатор 3 — 3 раза. Мне нужен последний идентификатор 1 и последний идентификатор 3.

Вывод:

 const frequentItems = [
  {id: 3, date: new Date('2020/8/4')},
  {id: 1, date: new Date('2020/8/4')},
]
  

Знаете ли вы самый простой и действенный способ сделать это?

Комментарии:

1. что вы уже пробовали?

2. Моя идея состояла в том, чтобы создать промежуточные элементы, const counted которые будут {1: 3, 2: 2, 3: 3} , затем уменьшить упорядоченные по дате элементы и проверить, есть ли они в counts , затем найти последние. Я чувствую, что есть гораздо лучший способ сделать это.

3. Почему элемент с id = 2 не отображается в выходных данных? Редактировать: О, я понимаю! Вы продолжаете менять вопрос …

4. Вам нужны элементы, которые отображаются 2 или более раз, или 3 или более раз? Вы хотите найти id s, которые присутствуют по крайней мере столько раз, или значения , которые присутствуют по крайней мере столько раз?

5. Я хочу найти элементы, которые отображаются n раз или более ( n может быть 2 или 3). Я отредактировал свой вопрос, чтобы сделать его более понятным.

Ответ №1:

Наилучшая возможная среда выполнения — O (n), которая заключается в использовании алгоритма, подобного сортировке по количеству, с небольшим дополнительным объемом памяти O (n); ознакомьтесь с фрагментом ниже

 const items = [
  {id: 3, date: new Date('2020/8/3')},
  {id: 1, date: new Date('2020/8/1')},
  {id: 1, date: new Date('2021/8/2')},
  {id: 2, date: new Date('2020/8/1')},
  {id: 2, date: new Date('2020/8/4')},
  {id: 3, date: new Date('2022/8/3')},
  {id: 3, date: new Date('2020/8/4')},
  {id: 1, date: new Date('2020/8/3')},
];

// used to keep track of repetition number of each id;
const itemCount = Object.create(null);
// used to random access each object by its key later;
const keyIndexedObjects = Object.create(null);

items.forEach( item => {
  const currentItemDate = new Date( item.date );
  const prevoiusItemDate = new Date( (keyIndexedObjects[item.id]||{}).date);

  // only update key index object if its date is bigger than prevoius date
  if(!(prevoiusItemDate amp;amp;
  (prevoiusItemDate > currentItemDate))){
    keyIndexedObjects[item.id] = item;
  }
  
  itemCount[item.id] = (itemCount[item.id] || 0)   1;
});

const desiredOutput = [];

for ( const [key, value] of Object.entries(itemCount) ){
  if( value >= 3 ) desiredOutput.push(keyIndexedObjects[key])
}

console.log(desiredOutput)  

Ответ №2:

Вы можете дважды выполнить цикл по элементам: первый раз, чтобы запомнить количество каждого элемента (в object counts в приведенном ниже коде) и запомнить последнюю версию каждого элемента (object latest ), а второй раз, чтобы собрать только те, которые считаются более чем в два раза.

 let counts = {};
let latest = {};
for(let x of items) {
    if(!counts[x.id]) counts[x.id] = 0;
    counts[x.id]  ;
    if(!latest[x.id] || latest[x.id].date < x.date) latest[x.id] = x;
}

let frequentItems  = [];
for(let id in counts) {
    if(counts[id] > 2) frequentItems.push(latest[id]);
}
  

Ответ №3:

Вы также могли бы использовать Set

Он по определению содержит / не должен содержать повторяющийся элемент.

  1. Создайте новый набор

let dataSet = new Set()

2. Выполните итерацию по данным и добавьте id элементов в набор

dataSet.add(item.id)

  1. Результирующий набор данных будет содержать уникальный идентификатор

Комментарии:

1. это не то, о чем просил OP