javascript - 根据自定义逻辑减少对象数组
问题描述
我试图通过基于逻辑合并它们之间的键来减少对象数组。
解释
我想通过它们的键来减少以下数组(见下文):
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);
推荐阅读
- javascript - 几秒钟后如何加载漂移
- android - 为什么所有后退导航方法都不起作用?
- google-cloud-sql - 如何在 gcloud SQL 实例上记录所有 DDL?
- mysql - 使用带有反射的 Flask Sqlalchemy 选择实体
- cassandra - cassandra 真的是 NoSQL 数据库吗?
- javascript - eachLayer 与 onEachFeature 之间的区别
- javascript - 指示 TypeScript 需要哪种返回类型
- linux - 氧化:交换机备份输出配置文件格式-DeviceName/IP-YYYY:DD:MM:HH:SS
- ruby - 在 ruby 中接收来自 IP 255.255.255.255 的广播数据包
- python-3.x - python mongodb over cosmosdb 通过字段获取具有最大日期组的行