我试图通过基于逻辑合并对象之间的键来减少对象的数组。
解释
我想通过它们的密钥来减少以下数组(见下文(:
lines
:合并它们之间共同的数字范围(例如:[1,2]+[3,2]=[1,2,3](dates
:合并与lines
键关联的数组日期
应删除所有重复数据消除的数组和/或键。
示例:
输入示例A:
const errors = [
{
"lines": [1, 2],
"dates": [["2020-12-12","2020-12-19"], ["2020-12-13","2020-12-25"]]
},
{
"lines": [1, 3],
"dates": [["2020-12-12","2020-12-19"], ["2020-12-15","2020-12-17"]]
},
{
"lines": [2, 3],
"dates": [["2020-12-13","2020-12-25"], ["2020-12-15","2020-12-17"]]
},
{
"lines": [3, 2],
"dates": [["2020-12-15","2020-12-17"], ["2020-12-13","2020-12-25"]]
}
]
输出示例A:
const expected = [{
lines: [1, 2, 3],
dates: [
["2020-12-12", "2020-12-19"],
["2020-12-13", "2020-12-25"],
["2020-12-05", "2020-12-20"],
["2020-12-15", "2020-12-17"]
]
}];
输入示例B:
const errors = [
{
lines: [1, 2],
dates: [["2020-12-12", "2020-12-19"], ["2020-12-04", "2020-12-25"]]
},
{
lines: [1, 5],
dates: [["2020-12-12", "2020-12-19"], ["2020-12-05", "2020-12-20"]]
},
{
lines: [2, 5],
dates: [["2020-12-04", "2020-12-25"], ["2020-12-05", "2020-12-20"]]
},
{
lines: [3, 4],
dates: [["2020-10-19", "2020-10-25"], ["2020-10-24", "2020-10-27"]]
},
{
lines: [4, 3],
dates: [["2020-10-24", "2020-10-27"], ["2020-10-19", "2020-10-25"]]
},
{
lines: [5, 2],
dates: [["2020-12-05", "2020-12-20"], ["2020-12-04", "2020-12-25"]]
}
];
输出示例B:
const expected = [
{
lines: [1, 2, 5],
dates: [
["2020-12-12", "2020-12-19"],
["2020-12-04", "2020-12-25"],
["2020-12-05", "2020-12-20"]
]
},
{
lines: [3, 4],
dates: [
["2020-10-19", "2020-10-25"],
["2020-10-24", "2020-10-27"]
]
}
];
我创建了一个沙盒来实现这一点:https://codesandbox.io/s/lodash-sandbox-zsr9r
有三个例子,第三个不起作用。
我目前的实现:
const sanatizeErrors = errors.reduce((acc, currentError, i) => {
const nextError = errors[i + 1]
const hasOnlySingleError = errors.length === 1
// The following const is not enough "strong" and it doesn't handle all cases
const hasCommonErrorWithNextLine =
nextError && _.includes(nextError.lines, currentError.lines[0])
if (hasOnlySingleError) {
return [{
lines: currentError.lines,
dates: currentError.dates
}]
}
if (hasCommonErrorWithNextLine) {
return [
...acc,
{
lines: _.uniq([
...currentError.lines,
...nextError.lines
]),
dates: _.uniqWith(
[
...currentError.dates,
...nextError.dates
], _.isEqual)
}
]
}
return acc
}, [])
此最终数组用于处理动态日期范围重叠
任何亮点都值得赞赏=(
只要条件相当复杂,数据结构也很复杂,代码就会相当混乱。我很乐意检查其他想法。我在代码段中添加了注释来解释逻辑。如果您有任何问题,欢迎
const errors = [
{
lines: [1, 2],
dates: [["2020-12-12", "2020-12-19"], ["2020-12-04", "2020-12-25"]]
},
{
lines: [1, 5],
dates: [["2020-12-12", "2020-12-19"], ["2020-12-05", "2020-12-20"]]
},
{
lines: [2, 5],
dates: [["2020-12-04", "2020-12-25"], ["2020-12-05", "2020-12-20"]]
},
{
lines: [3, 4],
dates: [["2020-10-19", "2020-10-25"], ["2020-10-24", "2020-10-27"]]
},
{
lines: [4, 3],
dates: [["2020-10-24", "2020-10-27"], ["2020-10-19", "2020-10-25"]]
},
{
lines: [5, 2],
dates: [["2020-12-05", "2020-12-20"], ["2020-12-04", "2020-12-25"]]
}
];
let output = errors.reduce((acc,rec) => {
let i;
//iterate through elements of accumulator to check where to merge
for (i = 0; i < acc.length; i++) {
let current = acc[i]
// if there are duplicates
if(current.lines.map(it => rec.lines.indexOf(it) > -1).some(it => it))
{
// combine and merge (remove duplicates) arrays of lines
acc[i].lines = (acc[i].lines.concat(rec.lines)).filter((it, i, arr) => arr.indexOf(it) === i)
// combine and merge (remove duplicates) arrays of dates. In filter complex check to find lastPosition of elements. IndexOf wont't work when arrays are compared (as works for lines)
acc[i].dates = (acc[i].dates.concat(rec.dates)).filter((it, i, arr) => {
const lastPosition = arr.reduce((acc,rec, idx) => rec[0] === it[0] && rec[1] === it[1] ? idx: acc, 0)
return i === lastPosition
})
// if place for merge has been found - finish
return acc
}
}
// if there is no place for merge - add new group
return [...acc, rec]
},[])
console.log('result', output);