使用lodash从数组中筛选冗余对象
Filter redundant objects from array with lodash
数据
var ranges = [
{ start: 2, end: 5 },
{ start: 8, end: 12 },
{ start: 15, end: 20 },
{ start: 9, end: 11 },
{ start: 2, end: 6 }
];
每个对象表示一个范围。我需要删除包含在另一个范围中的范围。也就是说,在两个冗余对象之间,我需要保持更长的范围。
我写了这段代码,但我想知道是否有更好的方法可以使用lodash实现这一点。
var Range = {
contains: function(r1, r2) {
return r2.start >= r1.start && r2.end <= r1.end;
}
};
var result = _.chain(ranges)
.filter(function(r2) {
return !_.some(ranges, function(r1) {
return r1 != r2 && Range.contains(r1, r2);
});
})
.value();
console.log(result);
输出
[
{ start: 8, end: 12 },
{ start: 15, end: 20 },
{ start: 2, end: 6 }
]
我终于找到了一种使用uniqWith实现这一点的简单方法。
var result = _.chain(ranges)
.orderBy(['end'], ['desc'])
.uniqWith(function(r1, r2) {
return Range.contains(r2, r1);
})
.value();
我真的很喜欢你的解决方案,但你可以用_.difference写得更紧凑一点。如果你喜欢的话,用:
var result = _.differenceWith(ranges, ranges, function(r1, r2) {
return !_.isEqual(r1, r2) && r1.start >= r2.start && r1.end <= r2.end;
});
var ranges = [
{ start: 2, end: 5 },
{ start: 8, end: 12 },
{ start: 15, end: 20 },
{ start: 9, end: 11 },
{ start: 2, end: 6 }
];
var result = _.differenceWith(ranges, ranges, function(r1, r2) {
return !_.isEqual(r1, r2) && r1.start >= r2.start && r1.end <= r2.end;
});
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>
当您没有那么多范围时,这些解决方案非常有效。如果你有一个大数组,那么可能值得使用两个常规while循环:
function between(r1, r2) {
return r1.start >= r2.start && r1.end <= r2.end;
}
var i = ranges.length;
while(i) {
--i;
var r1 = ranges[i];
var j = i;
while(j) {
--j;
var r2 = ranges[j];
if(between(r1, r2)) {
ranges.splice(i, 1);
break;
} else if (between(r2, r1)) {
ranges.splice(j, 1);
--i;
}
}
}
var ranges = [
{ start: 2, end: 5 },
{ start: 8, end: 12 },
{ start: 15, end: 20 },
{ start: 9, end: 11 },
{ start: 2, end: 6 }
];
function between(r1, r2) {
return r1.start >= r2.start && r1.end <= r2.end;
}
var i = ranges.length;
while(i) {
--i;
var r1 = ranges[i];
var j = i;
while(j) {
--j;
var r2 = ranges[j];
if(between(r1, r2)) {
ranges.splice(i, 1);
break;
} else if (between(r2, r1)) {
ranges.splice(j, 1);
--i;
}
}
}
console.log(ranges);
如果您想避免对大型数据集进行冗余比较,可以在比较之前对范围进行排序:
var sorted = _.orderBy(ranges, ['start', 'end'], ['desc', 'asc']);
var result = _.chain(sorted)
.filter(function(r2, i) {
//Only the items after r2 may contain r2 so we slice the array.
return !_.some(_.slice(sorted,i+1), function(r1) {
// You could just test if r2.end <= r1.end here
// We already know that r2.start >= r1.start
return Range.contains(r1, r2);
});
})
.value();
r2
之前的所有项目都从r2
之后开始,不能包含它,所以我们不比较它们。
我不认为lodash提供了任何开箱即用的方法。
纯JavaScript(ES6(不是一个选项吗?
ranges = ranges
.sort( (a,b) => a.start - b.start || b.end - a.end )
.reduce( (acc,a,i,ranges) => a.end > acc[1] ? [acc[0].concat([a]), a.end] : acc, [[],0] )
[0];
var ranges = [
{ start: 2, end: 5 },
{ start: 8, end: 12 },
{ start: 15, end: 20 },
{ start: 9, end: 11 },
{ start: 2, end: 6 }
];
ranges = ranges
.sort( (a,b) => a.start - b.start || b.end - a.end )
.reduce( (acc,a,i,ranges) => a.end > acc[1] ? [acc[0].concat([a]), a.end] : acc, [[],0] )
[0];
console.log(ranges);
相关文章:
- 缓存的最佳实践.避免冗余缓存
- UMD:正在分配给模块,导出冗余
- 如何更正阵列中的这种冗余
- Regex删除涉及零或一的冗余乘法/除法
- 删除方法中的冗余代码
- 多选择器冗余
- 简化冗余jquery's代码
- 排列具有相同数据的多个对象(减少冗余)
- Meteor模板-继承或外包事件以避免代码冗余
- HTML-减少HTML代码冗余
- 如果我两次使用相同的反应/冗余组件,它们会共享状态吗?
- 等待多个 ipc 调用完成,然后再继续电子/冗余
- 在 Javascript 中模拟“IN”运算符以简化冗余逻辑 OR 的最佳解决方案是什么?
- elasticsearch:保留冗余(非规范化)数据或保留 id 列表以进行交叉引用
- 如何获取调度冗余
- 编写函数以防止冗余
- 如何避免客户端验证中的冗余条件
- 同构反应-路由器-冗余同步历史中间件
- ExtJS - 如何创建可重用的函数以避免代码冗余
- 使用lodash从数组中筛选冗余对象