#javascript #arrays #filter
Вопрос:
Итак, у меня есть массив, который выглядит так:
[
{ date: '2021-07-07' },
{ date: '2021-07-07' },
{ date: '2021-07-07' },
{ date: '2021-07-08' },
{ date: '2021-07-09' },
{ date: '2021-07-10' },
{ date: '2021-07-10' }
];
Как я могу разделить массив на 3 (я имею в виду 1 группу для уникальных дат и другую группу для дубликатов, но если их более 1, она должна разделиться на другую группу)
Это будет выглядеть так после разделения
Array 1
[{"date": "2021-07-07"},{"date": "2021-07-07"},{"date": "2021-07-07"}]
Array 2
[{"date": "2021-07-08"},{"date": "2021-07-09"}]
Array 3
[{"date": "2021-07-10"},{"date": "2021-07-10"}]
Ниже приведен мой код до сих пор, но он работает только в том случае, если дубликат на 1
const findDuplicates = arr => {
let sorted_arr = arr.slice().sort();
let result = [];
for (let i = 0; i < sorted_arr.length - 1; i ) {
if (sorted_arr[i 1].date == sorted_arr[i].date) {
result.push(sorted_arr[i]);
}
}
return resu<
};
const filterSame = arr => {
let temp = findDuplicates(arr);
const result = arr.filter(date => date.date == temp[0].date);
return resu<
};
const filterUnique = array => {
let result = array.filter(
(e, i) => array.findIndex(a => a['date'] === e['date']) === i
);
let temp = findDuplicates(array);
result = result.filter(function(obj) {
return obj.date !== temp[0].date;
});
return resu<
};
Комментарии:
1. Почему
2021-07-08
и2021-07-09
сгруппированы вместе?2. @adiga, потому что это больше, чем просто простая группировка. Это группировка, за которой следует объединение всего с помощью только 1 элемента.
3. Я понял это как сгруппировать все элементы по дате, где есть дубликаты, но затем создать другую группу для всех уникальных дат. Это в основном основано на ожидаемом результате TBH
4. @Jamiec уникальные переходят в группу, а дубликаты-в отдельные группы?
5. вот как я понял вопрос «да». Это не особенно хорошо описано, но в этом, безусловно, есть нечто большее, чем простая группа, созданная в соответствии с обманом
Ответ №1:
Вы можете создать карту с указанием дат и значением в качестве пустого массива. Затем заполните эти массивы. Наконец, извлеките массивы, содержащие более одного элемента, и добавьте к этому результату объединенный массив из этих одноэлементных массивов:
function group(data) {
let map = new Map(data.map(o => [o.date, []]));
for (let o of data) map.get(o.date).push(o);
return [
...[...map.values()].filter(({length}) => length > 1),
[...map.values()].filter(({length}) => length == 1).flat()
];
}
let data = [{"date":"2021-07-07"},{"date":"2021-07-07"},{"date":"2021-07-07"},{"date":"2021-07-08"},{"date":"2021-07-09"},{"date":"2021-07-10"},{"date":"2021-07-10"}];
console.log(group(data));
Объяснение
let map = new Map(data.map(o => [o.date, []]));
Это создает карту. Конструктору дается массив пар. Для примера данных этот массив выглядит следующим образом:
[
["2021-07-07", []],
["2021-07-07", []],
["2021-07-07", []],
["2021-07-08", []],
["2021-07-09", []],
["2021-07-10", []],
["2021-07-10", []]
]
Конструктор карт создаст соответствующую карту, которая действительно удаляет дубликаты. Вы можете представить это следующим образом (хотя это не простой объект).:
{
"2021-07-07": [],
"2021-07-08": [],
"2021-07-09": [],
"2021-07-10": []
}
Затем for
цикл заполнит эти (четыре) массива, так что карта будет выглядеть следующим образом:
{
"2021-07-07": [{date:"2021-07-07"},{date:"2021-07-07"},{date:"2021-07-07"}],
"2021-07-08": [{date:"2021-07-08"}],
"2021-07-09": [{date:"2021-07-09"}],
"2021-07-10": [{date:"2021-07-10"},{date:"2021-07-10"}]
}
В return
инструкции значения карты дважды преобразуются в массив. Один раз для фильтрации записей, содержащих более 1 элемента:
[
[{date:"2021-07-07"},{date:"2021-07-07"},{date:"2021-07-07"}],
[{date:"2021-07-10"},{date:"2021-07-10"}]
]
…и второй раз, чтобы получить те, у которых есть 1 элемент:
[
[{date:"2021-07-08"}],
[{date:"2021-07-09"}],
]
Второй массив сплющен с flat()
:
[
{date:"2021-07-08"},
{date:"2021-07-09"},
]
Конечный результат объединяет первый массив (с повторяющимися датами) с уплощенным массивом (с уникальными датами), используя синтаксис распространения ( ...
)
Комментарии:
1. Я так предпочитаю этот ответ своему собственному. Мило!
2. это работает, это очень хорошо, если вы оставите какой-нибудь комментарий, чтобы я мог знать, что происходит, но в любом случае спасибо.
3. Добавил объяснение к моему ответу. Надеюсь, это прояснит ситуацию.
4. Этот ввод имеет вложенную структуру (массив массивов объектов), в то время как ваш вопрос содержит массив объектов. Поэтому в этом случае вы должны сначала применить
.flat()
свои входные данные, прежде чем передавать их функции в моем ответе. Конечно, важно, чтобы ваш ввод имел последовательную форму .5. Реализовали ли вы призыв к
.flat()
тому, что у меня есть в моем ответе (я добавил его немного после публикации первоначального ответа)?
Ответ №2:
Это можно было бы сделать в 2 этапа
- типичная группировка по операциям на основе
date
свойств - объединение всех групп, которые имеют только 1 результат.
const input = [{"date":"2021-07-07"},{"date":"2021-07-07"},{"date":"2021-07-07"},{"date":"2021-07-08"},{"date":"2021-07-09"},{"date":"2021-07-10"},{"date":"2021-07-10"}]
const grouped = input.reduce ( (acc,i) => {
if(!acc[i.date]) acc[i.date] = []
acc[i.date].push(i);
return acc;
},{});
const final = Object.values(Object.entries(grouped).reduce( (acc,[key,values]) => {
if(values.length>1) {
acc[key] = values;
}
else{
if(!acc.others) acc.others = [];
acc.others.push(values[0]);
}
return acc
},{}))
console.log(final);
Обратите внимание, что если вы добавите, например, 2021-07-11
в свой исходный массив, это будет объединено со всеми другими «уникальными» элементами. Это может быть или не быть тем, чего вы ожидали, но не было ясно из вопроса.
Ответ №3:
Другой вариант-обратиться к sort
массиву перед группировкой. Если date
зацикливаемый ток не совпадает со своими соседями, то у него нет дубликатов.
const input = [{"date":"2021-07-07"},{"date":"2021-07-07"},{"date":"2021-07-07"},{"date":"2021-07-08"},{"date":"2021-07-09"},{"date":"2021-07-10"},{"date":"2021-07-10"}]
input.sort((a,b) => a.date.localeCompare(b.date))
const grouped = input.reduce((acc, o, i, arr) => {
const key = o.date === arr[i-1]?.date || o.date === arr[i 1]?.date
? o.date
: 'lonely'
acc[key] ||= []
acc[key].push(o);
return acc;
}, {});
console.log(Object.values(grouped));