给定一个时间列表,如何将它们分组,使接近的时间在同一组中而远的不在?

问题描述

假设我有一个日期类型为 zoneddatetime 的时间戳列表。 我不想将它们打印出来,而是希望能够以某种方式将它们分组,并且只打印间隔,例如

07:41:05 - 07:55:46
08:21:35 - 08:45:42  //first being the first elem of the group,second being the last
etc

我只是想先将它们全部转换为毫秒,然后对时间戳进行排序,并且可能选择一个像 100000 毫秒这样的值作为分隔符,因此如果两个时间戳毫秒值相距小于 100000 毫秒,我将它们视为一部分同一组。

在最坏的情况下,所有时间戳在排序时都在这个距离内,然后我有一个巨大的组,其中间隔的开始和结束元素相隔几个小时,但我希望给定的数据集不太可能发生这种情况。

有没有更好的方法来做到这一点? 问题尚未得到解答。

解决方法

使用 k 均值:

// sample data
List<ZonedDateTime> xs = IntStream.range(0,10).mapToObj(n ->
        ZonedDateTime.now().truncatedTo(ChronoUnit.DAYS)
                .plus(ThreadLocalRandom.current().nextInt(0,24 * 60),ChronoUnit.MINUTES))
        .collect(toList());

// assume xs is not empty
ZonedDateTime day = xs.get(0).truncatedTo(ChronoUnit.DAYS);

final int WINDOWS = 3;

System.out.printf("== fixed windows (millis precision) using k-means%n");
Map<Double,List<ZonedDateTime>> points = xs.stream()
        .collect(groupingBy(x -> (double) ((x.toInstant().toEpochMilli() - day.toInstant().toEpochMilli()) / 1000),toList()));
Double[] keys = points.keySet().stream().sorted().toArray(Double[]::new);
double[][] kpoints = new double[keys.length][2];
// put keys along f(x)=0 line
for (int i = 0; i < keys.length; i++) {
    kpoints[i][0] = keys[i];
    kpoints[i][1] = 0;
}
double[][] centroids = new double[WINDOWS][2];
for (int i = 0; i < WINDOWS; i++) {
    centroids[i][0] = ThreadLocalRandom.current().nextDouble(keys[0],keys[keys.length - 1]);
    centroids[i][1] = 0;
}
final EKmeans eKmeans = new EKmeans(centroids,kpoints);
eKmeans.run();
// regroup
int[] igroup = eKmeans.getAssignments();
Map<Integer,List<ZonedDateTime>> groups =
        IntStream.range(0,igroup.length).boxed()
                .collect(groupingBy(i -> igroup[i],collectingAndThen(toList(),rs -> rs.stream().flatMap(r -> points.get(keys[r]).stream()).collect(toList()))));
groups.forEach((k,rs) -> {
    System.out.printf("  - group %d%n",k);
    rs.forEach(r -> System.out.printf("   %s%n",r.format(ISO_LOCAL_TIME)));
});

带输出

== fixed windows (millis precision) using k-means
  - group 0
   03:09:00
   03:22:00
   05:22:00
   05:38:00
   07:34:00
  - group 1
   16:30:00
   18:25:00
  - group 2
   11:23:00
   11:48:00
   14:07:00

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...