Попытка фильтровать массив объектов путем исключения объектов, которые имеют определенное свойство, существующее уже в другом объекте (дубликат). Решение, которое следует удалить, должно основываться на другом свойстве.
Пример. Для массива объектов, который может выглядеть так, цель будет состоять в том, чтобы отфильтровать все "пользовательские" дубликаты и сохранить один со старым свойством "date".
const arr = [
{user: 'Alex', date: '1540801929945'},
{user: 'Bill', date: '1640801929946'},
{user: 'Carl', date: '1740801929947'},
{user: 'Alex', date: '1840801929948'},
]
Ожидаемый результат:
filteredArr = [
{user: 'Alex', date: '1540801929945'},
{user: 'Bill', date: '1640801929946'},
{user: 'Carl', date: '1740801929947'},
]
Я управлял базовой фильтрацией, которая работает для хранения только уникальных объектов.
const filteredArr = arr.reduce((unique, o) => {
if(!unique.some(obj => obj.user === o.user) {
unique.push(o);
}
return unique;
},[]);
Хотя я не могу понять, что делать, чтобы в случае дубликата остался "самый старый" объект и последние удалены. Большое спасибо за Вашу помощь! Действительно оценен.
Уменьшите массив до объекта с помощью user
в качестве ключа. Если пользователь не находится в unique
объекте или если дата "старше", чем то, что есть, добавьте его в объект. Преобразуйте объект в массив с помощью Object.values()
.
Примечание. Поскольку вы дате строки, преобразуйте их в число при сравнении (я использую оператор +
).
const array = [{ user: 'Alex', date: '1540801929945' }, { user: 'Bill', date: '1640801929946' }, { user: 'Carl', date: '1740801929947' }, { user: 'Alex', date: '1840801929948' }];
const filteredArray = Object.values(array.reduce((unique, o) => {
if(!unique[o.user] || +o.date > +unique[o.user].date) unique[o.user] = o;
return unique;
}, {}));
console.log(filteredArray);
+o.date < +unique[o.user].date)
(...) - но в остальном это похоже на работу. Большое спасибо за помощь!
date
, а не dateofpost
.
Решение с Map
и подход с единой петлей
var array = [{ user: 'Alex', date: '1540801929945' }, { user: 'Bill', date: '1640801929946' }, { user: 'Carl', date: '1740801929947' }, { user: 'Alex', date: '1840801929948' }],
filtered = Array.from(array
.reduce((m, o) => !m.has(o.user) || m.get(o.user).data > o.date
? m.set(o.user, o)
: m, new Map)
.values());
console.log(filtered);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Для отсортированных данных (предварительно отсортируйте их по date
) вы можете использовать Set
для фильтрации.
var array = [{ user: 'Alex', date: '1540801929945' }, { user: 'Bill', date: '1640801929946' }, { user: 'Carl', date: '1740801929947' }, { user: 'Alex', date: '1840801929948' }],
filtered = array
.sort(({ date: a }, { date: b }) => a - b)
.filter((s => ({ user }) => !s.has(user) && s.add(user))(new Set));
console.log(filtered);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Я считаю, что вам действительно нужно знать индекс не уникального элемента (Object с именем "Alex" в вашем случае), а затем сравнить их даты, сохранив более старый.
Array.prototype.find wil lnot, вы отлично разбираетесь в этом случае. Тем не менее, Array.prototype.find может помочь, так как он принимает обратный вызов, который возвращает логическое значение (как и "some"), но он возвращает индекс элемента, соответствующий вашему обратному вызову, или undefined, если такой элемент не найден.
Дайте ему попробовать, это не больно :)
Для решения O(N)
reduce
объект, проиндексированный user
, значения которого - date
- на каждой итерации, если что-то у этого user
уже существует, сохраняйте только самую низкую date
. Затем перебираем entries
объекта, чтобы вернуть их обратно в массив:
const arr = [
{user: 'Alex', date: '1540801929945'},
{user: 'Bill', date: '1640801929946'},
{user: 'Carl', date: '1740801929947'},
{user: 'Alex', date: '1840801929948'},
{user: 'Carl', date: '1340801929947'},
];
const arrByUser = arr.reduce((a, { user, date }) => {
if (!a[user]) a[user] = date;
else if (a[user].localeCompare(date) === 1) a[user] = date;
return a;
}, {});
const output = Object.entries(arrByUser)
.map(([user, date]) => ({ user, date }));
console.log(output);
date
?