这些天我正在学习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或电子书的好网站?
答案 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
),那么就去做吧。但如果不是,那么上面较长的定义会更好。