#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
Он по определению содержит / не должен содержать повторяющийся элемент.
- Создайте новый набор
let dataSet = new Set()
2. Выполните итерацию по данным и добавьте id элементов в набор
dataSet.add(item.id)
- Результирующий набор данных будет содержать уникальный идентификатор
Комментарии:
1. это не то, о чем просил OP