数据点按时间间隔以及数据值分割数据块
作者:waitmoon
- 2022 年 8 月 24 日 上海
本文字数:1966 字
阅读完需:约 6 分钟
背景:
在 SLO 等分析场景中,常常会保存一些异常数据点,如何根据这些数据点简单分隔出更有价值且传输消耗更小的分割区间?
例:
如现有 3 个数据点(时间戳-值) 1-0.5,10-0.9,11-0.9 如若定义值≥0.9 为 error 区间,≥0.5 为 warn 区间,低于 0.5 为 common,间隔为 5,开始时间 1,结束时间 20
则应输出 warn(1,6], common(6,10], error(10,16], common(16,20]
其中 10 和 11 有两个 error 数据点,但因为间隔小于 5,则合并为一个分割区间,6 到 10 和 16 到 20 补充为 common 区间
Code:
import javafx.util.Pair;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
public class Test {
/**
* 数据点按时间间隔以及数据值分割数据块
* 背景:在SLO等分析场景中,常常会保存一些异常数据点,如何根据这些数据点产出更有价值的区间范围?
* 例子:如现有3个数据点(时间戳-值) 1-0.5,10-0.9,11-0.9 如若定义值≥0.9为error区间,≥0.5为warn区间,低于0.5为common,间隔为5,开始时间1结束时间20
* 则应输出warn(1,6], common(6,10], error(10,16], common(16,20]
* 其中10和11有两个error数据点,但因为间隔小于5,则合并为一个分割区间,6到10和16到20补充common区间
*
* @param args args
*/
public static void main(String[] args) {
//数据点 Pair<时间戳,数据值>
List<Pair<Integer, Double>> points = Arrays.asList(new Pair<>(1, 0.5), new Pair<>(10, 0.9), new Pair<>(11, 0.9));
//分割配置 Pair<分割信息,分割值>
List<Pair<String, Double>> separations = Arrays.asList(new Pair<>("error", 0.9), new Pair<>("warn", 0.5));
//时间间隔
long interval = 5;
//空余填充
String fillingSeparation = "common";
//开始时间
long start = 1;
//结束时间
long end = 20;
//分割结果
String openSeparation = fillingSeparation;
long separationStartTs = start;
long separationContinueTs = separationStartTs + interval;
List<Result> results = new LinkedList<>();
for (Pair<Integer, Double> point : points) {
long ts = point.getKey();
double value = point.getValue();
if (ts > separationContinueTs) {
//上一个分割区间不足以延续,使用空余填充
if (!openSeparation.equals(fillingSeparation)) {
results.add(new Result(openSeparation, separationStartTs, separationContinueTs));
openSeparation = fillingSeparation;
separationStartTs = separationStartTs + interval;
}
}
for (Pair<String, Double> separation : separations) {
if (value >= separation.getValue()) {
if (!openSeparation.equals(separation.getKey()) && separationStartTs != ts) {
//状态发生转变,结束上一个分割区间,开启新的分割区间
results.add(new Result(openSeparation, separationStartTs, ts));
separationStartTs = ts;
}
openSeparation = separation.getKey();
break;
}
}
separationContinueTs = ts + interval;
}
//尾部处理
if (end > separationContinueTs) {
results.add(new Result(openSeparation, separationStartTs, separationContinueTs));
openSeparation = fillingSeparation;
separationStartTs = separationContinueTs;
}
results.add(new Result(openSeparation, separationStartTs, end));
System.out.println(results);
}
private static class Result {
//区间分割符
private final String separator;
//区间开始时间
private final long start;
//区间结束时间
private final long end;
public Result(String separator, long start, long end) {
this.separator = separator;
this.start = start;
this.end = end;
}
@Override
public String toString() {
return separator + "(" + start + "," + end + "]";
}
}
}
复制代码
划线
评论
复制
发布于: 刚刚阅读数: 5
waitmoon
关注
致力于解决灵活繁复的硬编码问题~ 2020.03.30 加入
来都来了,坐下喝茶~看看ice~~
评论