在元素上拆分条件为的数组



所以我有一个数组,如下所示:

[
{ 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"},
]

最终结果使用排列语法(...(将第一个数组(具有重复日期(与扁平数组(具有唯一日期(连接起来

这可以在两步过程中完成

  1. 基于date性质的典型群
  2. 将仅具有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));

最新更新