简体   繁体   English

两组数据的交集

[英]intersection of two sets of data

I've been cracking my head over this algorithm for the past week and a half and i cant get it to work. 在过去的一个半星期中,我一直在努力研究这种算法,但我无法使其正常工作。

Basically i have an schedule (i know the Time value of the "borders") and i have the red section (peoples movements in and out of the workplace). 基本上,我有一个时间表(我知道“边界”的时间值),而我有一个红色部分(人们进出工作场所的动向)。 What i want is to know the time people spend at the workplace WITHIN their schedule, i dont care if they are there before or after work, or in the lunch break. 我想知道的是人们在时间表内花在工作场所上的时间,我不在乎他们是在上班前还是下班后,或者在午休时间。

do you have any suggestions? 你有什么建议吗? on a mathematical theory or rule that i can apply here? 我可以在这里应用的数学理论或规则? or a similar problem you have seen you can point me to? 或您看到的类似问题可以指出我的观点? i've been having a really hard time finding a solution. 我一直很难找到解决方案。 Any help would be appreciated. 任何帮助,将不胜感激。

图片

For example: 例如:

Schedule: 时间表:
7:30am (start) 12:00pm(lunchbreak) 上午7:30(开始)12:00 pm(午餐)
1:30pm(endLunchBreak) 5:00pm(endOfWorkday) 1:30 pm(endLunchBreak)5:00 pm(endOfWorkday)

People movements trough the day: 一天中人们的动向:
IN: 6:50am, OUT: 6:55am 进:6:50 am,出:6:55 am
IN: 7:00am, OUT: 11:45am 进:7:00 am,出:11:45 am
IN: 1:45pm, OUT: 5:05pm 进:1:45 pm,出:5:05 pm

So, my expected output would be a timespan of: 7:30 (it ignores time IN workplace outside of work schedule) 因此,我的预期输出为以下时间跨度:7:30(它忽略了工作时间表以外的工作时间)

I would treat this as a state machine problem. 我将其视为状态机问题。 There are four states: S+W+, S-W+, S+W-, SW-. 有四种状态:S + W +,S-W +,S + W-,SW-。 Scheduled time corresponds to S+ states, worker present to W+ states. 计划的时间对应于S +状态,工作人员对应于W +状态。 The objective is to add time in S+W+ to the intersection time. 目的是将S + W +中的时间添加到相交时间中。

The valid transitions are: 有效的过渡是:

S+W+ End of schedule -> S-W+
S+W+ Worker leaves -> S+W-
S-W+ Start of schedule -> S+W+
S-W+ Worker leaves -> S-W-
S+W- End of schedule -> S-W-
S+W- Worker arrives -> S+W+
S-W- Start of schedule -> S+W-
S-W+ Worker arrives -> S-W+

Process events in time order, starting in state SW-. 从状态SW-开始按时间顺序处理事件。 If two events happen at the same time, process in either order. 如果两个事件同时发生,则以任一顺序处理。

On transition into S+W+, note the time. 过渡到S + W +时,请注意时间。 On transition out of S+W+, subtract the last noted time from the time of the transition, and add the result to the intersection time. 从S + W +过渡出来时,从过渡时间中减去最后记下的时间,并将结果加到相交时间上。

Break the day into 1440 one minute increments. 以1分钟为增量将天数分成1440。 This is your set space. 这是您设置的空间。

  • Set "S", the scheduled minutes, is a subset of that space. 设置的分钟数“ S”是该空间的子集。
  • Set "W", the amount of time spent on the job, is a subset of that space. 设置“ W”(花费在工作上的时间)是该空间的子集。

The intersection of "S" and "W" is the amount of time the person was there within their schedule (in minutes - convert to hh:mm per your needs). “ S”和“ W”的交集是该人在时间表内到场的时间(以分钟为单位-根据您的需要转换为hh:mm)。

Using other set algorithms you can find when they should have been there but weren't, etc. 使用其他集合算法,您可以找到它们何时应到达但未到达的时间,等等。

You might want to look into using this library , but be careful, it completely ignores DateTime.Kind , is not time zone aware, and doesn't respect daylight saving time. 您可能想研究使用此库 ,但请注意,它完全忽略了DateTime.Kind ,它不识别时区,也不尊重夏时制。

  • It is safe to use on Utc kinds. Utc类型上使用是安全的。
  • Never use it on Local kinds. 切勿在Local种类上使用它。
  • If you use it on Unspecified kinds, make sure you understand what the context is. 如果对Unspecified类型使用它,请确保您了解上下文是什么。 If it could possibly be a local time in some time zone that has DST, then your results may or may not be correct. 如果可能是某个具有DST的时区中的本地时间,那么您的结果可能正确,也可能不正确。

Other than that, you should be able to use its intersection function. 除此之外,您应该能够使用其交集功能。

It sounds like LINQ should work well here. 听起来LINQ在这里应该可以正常工作。 I've whipped up a short example, using my Noda Time library as it has better support for "time of day" than .NET, but you could adapt it if necessary. 我举了一个简短的示例,使用我的Noda Time库,因为它比.NET更好地支持“一天中的时间”,但是您可以根据需要进行调整。

The idea is basically that you have two collections of periods, and you're only interested in the intersection - you can find the intersection of any schedule period against any movement period - it's easy to discount periods that don't intersect by just using a 0-length period. 这个想法基本上是,您有两个期间集合,并且您只对交叉点感兴趣-您可以找到任何计划周期与任何移动周期的交叉点-只需使用长度为0的时段。

Here's the complete code, which does indeed give a total time of 7 hours and 30 minutes: 这是完整的代码,它确实总共耗时7小时30分钟:

using System;
using System.Collections.Generic;
using System.Linq;
using NodaTime;

class Test
{
    static void Main()
    {
        var schedule = new List<TimePeriod>
        {
            new TimePeriod(new LocalTime(7, 30), new LocalTime(12, 0)),
            new TimePeriod(new LocalTime(13, 30), new LocalTime(17, 0)),
        };

        var movements = new List<TimePeriod>
        {
            new TimePeriod(new LocalTime(6, 50), new LocalTime(6, 55)),
            new TimePeriod(new LocalTime(7, 0), new LocalTime(11, 45)),
            new TimePeriod(new LocalTime(13, 45), new LocalTime(17, 05))
        };

        var durations = from s in schedule
                        from m in movements
                        select s.Intersect(m).Duration;
        var total = durations.Aggregate((current, next) => current + next);
        Console.WriteLine(total);
    }
}

class TimePeriod
{
    private readonly LocalTime start;
    private readonly LocalTime end;

    public TimePeriod(LocalTime start, LocalTime end)
    {
        if (start > end)
        {
            throw new ArgumentOutOfRangeException("end");
        }
        this.start = start;
        this.end = end;
    }

    public LocalTime Start { get { return start; } }
    public LocalTime End { get { return end; } }
    public Duration Duration { get { return Period.Between(start, end)
                                                  .ToDuration(); } }

    public TimePeriod Intersect(TimePeriod other)
    {
        // Take the max of the start-times and the min of the end-times
        LocalTime newStart = start > other.start ? start : other.start;
        LocalTime newEnd = end < other.end ? end : other.end;
        // When the two don't actually intersect, just return an empty period.
        // Otherwise, return the appropriate one.
        if (newEnd < newStart)
        {
            newEnd = newStart;
        }
        return new TimePeriod(newStart, newEnd);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM