所以我有一个数组,如下所示:
[
{ 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个数组(我的意思是,一组表示唯一日期,另一组表示重复,但如果有一个以上的重复组,则应划分为另一组(
拆分后会是这样
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 result;
};
const filterSame = arr => {
let temp = findDuplicates(arr);
const result = arr.filter(date => date.date == temp[0].date);
return result;
};
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 result;
};
您可以创建一个由日期键控的映射,并使用空数组作为值。然后填充这些数组。最后提取具有多个元素的数组,并将这些单个元素数组的组合数组添加到该结果中:
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, []]));
这将创建一个Map。构造函数被赋予了一个成对的数组。对于数组如下所示的示例数据:
[
["2021-07-07", []],
["2021-07-07", []],
["2021-07-07", []],
["2021-07-08", []],
["2021-07-09", []],
["2021-07-10", []],
["2021-07-10", []]
]
Map构造函数将创建相应的Map,这将真正删除重复项。你可以想象它如下(尽管它不是一个普通的对象(:
{
"2021-07-07": [],
"2021-07-08": [],
"2021-07-09": [],
"2021-07-10": []
}
然后for
循环将填充这(四个(数组,因此Map将如下所示:
{
"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
语句中,Map值被转换为数组两次。一次过滤具有一个以上元素的条目:
[
[{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"},
]
最终结果使用排列语法(...
(将第一个数组(具有重复日期(与扁平数组(具有唯一日期(连接起来
这可以在两步过程中完成
- 基于
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
添加到原始数组中,则这将与所有其他";独特的";元素。这可能是也可能不是你所期望的,但从问题中并不清楚。
另一个选项是在分组之前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));