时间范围内任何事件的最大发生次数 [英] Maximum occurrence of any event in time range

查看:217
本文介绍了时间范围内任何事件的最大发生次数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有收集时间戳记,例如 10:18:07.490,11:50:18.251 ,其中第一个是事件的开始时间,第二个是事件的结束时间。我需要找到一个范围,在此范围内仅24小时就会发生最多的事件。这些事件的发生以毫秒为单位。

I have collection time stamps, e.g 10:18:07.490,11:50:18.251 where first is the start time and second is end time for an event. I need to find a range where maximum events are happening just 24 hours of time. These events are happening in precision of milliseconds.

我正在做的是将24小时划分为毫秒级,并每毫秒附加一次事件,然后查找

What I am doing is to divide 24 hours on millisecond scale, and attach events at every millisecond, and then finding a range where maximum events are happening.

LocalTime start = LocalTime.parse("00:00");
LocalTime end = LocalTime.parse("23:59");


for (LocalTime x = start; x.isBefore(end); x = x.plus(Duration.ofMillis(1))) {
        for (int i = 0; i < startTime.size(); i++) {
        if (startTime.get(i).isAfter(x) && endTime.get(i).isBefore(x))
            // add them to list;
        }

    }

当然,这不是一个好方法,这会占用太多内存。我如何以适当的方式做到这一点?有建议吗?

Certainly this is not a good approach, it takes too much memory. How I can do it in a proper way? Any suggestion?

推荐答案

找到最大并发事件的第一期的解决方案:



如果您愿意使用第三方库,则可以使用jOOλ的窗口功能。这个想法与阿米特的答案中的解释相同:

A solution finding the first period of maximum concurrent events:

If you're willing to use a third party library, this can be implemented "relatively easy" in a SQL style with jOOλ's window functions. The idea is the same as explained in amit's answer:

System.out.println(
    Seq.of(tuple(LocalTime.parse("10:18:07.490"), LocalTime.parse("11:50:18.251")),
           tuple(LocalTime.parse("09:37:03.100"), LocalTime.parse("16:57:13.938")),
           tuple(LocalTime.parse("08:15:11.201"), LocalTime.parse("10:33:17.019")),
           tuple(LocalTime.parse("10:37:03.100"), LocalTime.parse("11:00:15.123")),
           tuple(LocalTime.parse("11:20:55.037"), LocalTime.parse("14:37:25.188")),
           tuple(LocalTime.parse("12:15:00.000"), LocalTime.parse("14:13:11.456")))
       .flatMap(t -> Seq.of(tuple(t.v1, 1), tuple(t.v2, -1)))
       .sorted(Comparator.comparing(t -> t.v1))
       .window(Long.MIN_VALUE, 0)
       .map(w -> tuple(
           w.value().v1,
           w.lead().map(t -> t.v1).orElse(null),
           w.sum(t -> t.v2).orElse(0)))
       .maxBy(t -> t.v3)
);

上面的照片:

Optional[(10:18:07.490, 10:33:17.019, 3)]

因此,在10:18 ...和10:33 ...之间的时间段内,发生了3个事件,这是一天中任何时间重叠的事件最多。

So, during the period between 10:18... and 10:33..., there had been 3 events, which is the most number of events that overlap at any time during the day.

请注意,在多个时段中,​​样本数据中有3个并发事件。 maxBy()仅返回第一个此类期间。为了返回所有这些期间,请使用 maxAllBy()(添加到jOOλ0.9.11中):

Note that there are several periods when there are 3 concurrent events in the sample data. maxBy() returns only the first such period. In order to return all such periods, use maxAllBy() instead (added to jOOλ 0.9.11):

   .maxAllBy(t -> t.v3)
   .toList()

然后屈服:

[(10:18:07.490, 10:33:17.019, 3), 
 (10:37:03.100, 11:00:15.123, 3), 
 (11:20:55.037, 11:50:18.251, 3), 
 (12:15       , 14:13:11.456, 3)]



或者图形表示形式



Or, a graphical representation

3                  /-----\       /-----\       /-----\       /-----\
2           /-----/       \-----/       \-----/       \-----/       \-----\
1     -----/                                                               \-----\
0                                                                                 \--
   08:15  09:37  10:18  10:33  10:37  11:00  11:20  11:50  12:15  14:13  14:37  16:57



说明:



这里是原始原始解决方案再次加上注释:

Explanations:

Here's the original solution again with comments:

// This is your input data    
Seq.of(tuple(LocalTime.parse("10:18:07.490"), LocalTime.parse("11:50:18.251")),
       tuple(LocalTime.parse("09:37:03.100"), LocalTime.parse("16:57:13.938")),
       tuple(LocalTime.parse("08:15:11.201"), LocalTime.parse("10:33:17.019")),
       tuple(LocalTime.parse("10:37:03.100"), LocalTime.parse("11:00:15.123")),
       tuple(LocalTime.parse("11:20:55.037"), LocalTime.parse("14:37:25.188")),
       tuple(LocalTime.parse("12:15:00.000"), LocalTime.parse("14:13:11.456")))

   // Flatten "start" and "end" times into a single sequence, with start times being
   // accompanied by a "+1" event, and end times by a "-1" event, which can then be summed
   .flatMap(t -> Seq.of(tuple(t.v1, 1), tuple(t.v2, -1)))

   // Sort the "start" and "end" times according to the time
   .sorted(Comparator.comparing(t -> t.v1))

   // Create a "window" between the first time and the current time in the sequence
   .window(Long.MIN_VALUE, 0)

   // Map each time value to a tuple containing
   // (1) the time value itself
   // (2) the subsequent time value (lead)
   // (3) the "running total" of the +1 / -1 values
   .map(w -> tuple(
       w.value().v1,
       w.lead().map(t -> t.v1).orElse(null),
       w.sum(t -> t.v2).orElse(0)))

   // Now, find the tuple that has the maximum "running total" value
   .maxBy(t -> t.v3)

我写了更多有关窗口功能以及如何实现

I have written up more about window functions and how to implement them in Java in this blog post.

(免责声明:我为jOOλ背后的公司工作)

(disclaimer: I work for the company behind jOOλ)

这篇关于时间范围内任何事件的最大发生次数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆