Linq - 如何使用上一个索引DateTime项减去当前索引DateTime项

时间:2013-08-30 20:53:56

标签: c# linq

这些天我正在学习Linq。我在stackoverflow或Google上搜索这个答案,但没找到我需要的东西。

飞行课程:

public class Flight
{
    public IList<Segment> Segments { get; set; }
}

这是我的细分类:

public class Segment
{
    public DateTime DepartureDate { get; set; }
    public DateTime ArrivalDate { get; set; }
}

每个航班由一个或多个航段组成。一段的飞行是这样的:威尼斯 - 费城。飞行有两个部分是威尼斯 - 费城,费城 - 旧金山。也可以有两个以上的细分。

我必须将Segment2.DepartureDate和Segment1.ArrivalDate之间的时间相加,以计算所有段中到达和下一次出发之间的时间差异。

我用foreach和这样的条件制作了这个字符串:

public string FilterFlights(IEnumerable<Flight> flights)
{
    string s = "";
    foreach (var flight in flights)
    {
    var indexItem = 0;
    DateTime previousArrivalDateTime = new DateTime();
    TimeSpan timeSpan;

    int time = 0;
    foreach (var segments in flight.Segments)
    {
        if (indexItem == 0)
        {
        previousArrivalDateTime = segments.ArrivalDate;
        s = s + "Departure: " + segments.DepartureDate + ", Arrival: " + segments.ArrivalDate + "; ";
        }

        if (indexItem > 0)
        {
        timeSpan = segments.DepartureDate - previousArrivalDateTime;
        time += timeSpan.Hours;
        s = s + "Departure: " + segments.DepartureDate + ", Arrival: " + segments.ArrivalDate + "; ";
        previousArrivalDateTime = segments.ArrivalDate;
        }
        indexItem++;
    }
    //d = 0;

    if (time > 2)
        Console.WriteLine(s);
    }

    return s;
}

我现在想要实际创建新方法而不是字符串,以返回IEnumerable<Flight>,我发现使用LinQ是最好的。我一直在用ElementAt方法嗅探,但不知道我到底在做什么。

修改 这是我用linq方法得到的:

public IEnumerable<Flight> FilterFlightsWithTwoHoursPlusGap(IEnumerable<Flight> flights)
{
    int totalGap = 0;

    return from flight in flights
       //wrong where syntax, don't know how to
    where flight.Segments.Select((y, index) =>
        totalGap +=
            (index == 0)
            ? totalGap = 0
            : (y.DepartureDate - flight.Segments.ElementAt(index - 1).ArrivalDate).Hours
        ).Where(totalGap < 2) // if gap is lower than 2 hours(calculated from timespans between departure current and arrival previous
    select flight; //return flights
}

所以任何建议都会很好。

PS:有没有学习linq或电子书的好网站?

1 个答案:

答案 0 :(得分:4)

查询

如果您希望在连续TimeSpan Flight之间的每个等待期间获得Segment s,则可以使用此选项:

Flight flight = ...;
IEnumerable<TimeSpan> query = flight.Segments
    .SelectPairs((a, b) => b.DepartureDate - a.ArrivalDate);

对于有Flight的{​​{1}},这会给你N - 1 Segments s。

修改:如果您想获得TimeSpan上所有Segment之间的等待时间总计,您可以像这样扩充LINQ查询:

Flight

辅助

TimeSpan totalWaitingTime = flight.Segments
    .SelectPairs((a, b) => b.DepartureDate - a.ArrivalDate)
    .Aggregate(TimeSpan.Zero, (s, t) => s + t);

注意

您可能想要定义public static IEnumerable<TResult> SelectPairs( this IEnumerable<T> source, Func<T, T, TResult> selector) { var first = true; var prev = default(T); foreach (var curr in source) { if (first) { first = false; } else { yield return selector(prev, curr); } prev = curr; } } ,如下所示:

SelectPairs

这里的缺陷是public static IEnumerable<TResult> SelectPairs( this IEnumerable<T> source, Func<T, T, TResult> selector) { return Enumerable.Zip(source, source.Skip(1), selector); } 将被枚举两次。如果在您的方案中这是可接受的(例如,如果source只是source),那么就去做吧。但如果不是,那么上面较长的定义会更好。