我正在进行API集成。 我有这样的模型
public class Flight
{
public string Origin{ get; set; }
public string Destination{ get; set; }
public string FlightNumber{ get; set; }
public string Provider{ get; set; }
}
这样的航班列表
List<Flight> Flight= new List<Flight>();
让我们假设这些是数据
Flight:
{
Segment1: { Origin= CMB , Destination=MAA , FlightNumber= 123, Provider= p}
Segment2: { Origin= MAA, Destination= DEL, FlightNumber= 543, Provider= p }
Segment3: { Origin= MAA, Destination= DEL, FlightNumber= 320, Provider= p}
Segment4: { Origin= CMB, Destination= BOM, FlightNumber= 644, Provider= p}
Segment5: { Origin= BOM, Destination= DEL, FlightNumber= 233, Provider= p}
Segment6: { Origin= CMB, Destination= KMG, FlightNumber= 233, Provider= p}
Segment7: { Origin= KMG, Destination= PEK, FlightNumber= 233, Provider= p}
Segment8: { Origin= PEK, Destination= DEL, FlightNumber= 233, Provider= p}
}
SearchingOrigin =“CMB”
SearchingDestination =“DEL”
我需要将这些项目分组,如下所示
Transit_segmentList---->[0]---->[0]{ Origin= CMB , Destination=MAA , FlightNumber= 123, Provider= p}
| [1]{ Origin= MAA, Destination= DEL, FlightNumber= 543, Provider= p }
| [2]{ Origin= MAA, Destination= DEL, FlightNumber= 320, Provider= p}
|
--->[1]---->[0]{ Origin= CMB, Destination= BOM, FlightNumber= 644, Provider= p}
| [1]{ Origin= BOM, Destination= DEL, FlightNumber= 233, Provider= p}
|
--->[2]---->[0]{ Origin= CMB, Destination= KMG, FlightNumber= 233, Provider= p}
[1]{ Origin= KMG, Destination= PEK, FlightNumber= 233, Provider= p}
[2]{ Origin= PEK, Destination= DEL, FlightNumber= 233, Provider= p}
我的主要来源是CMB,主要目的地是DEL。我想像这样分组他们
1)实际上,第1,2,3段是单次旅行的航班细节。飞机在前往 DEL 的路上停在 MAA 。段3是段2的备用段。 所以我想将这3个片段带到一个列表项( Transit_segmentList )。
2)同上面一样。飞行从CMB飞到DEL.It停在BOM。但这是一次旅行。我想把它作为第二次旅行到达 Transit_segmentList 。
3)段6,7,8也是同一行程的一部分。必须将它们排序为上图
答案 0 :(得分:0)
使用几种扩展方法,您可以生成所有航班组合并将其过滤到所需的航班组合,然后在第一个航班上将它们组合在一起。
以下是扩展方法:
public static IEnumerable<T> AsSingleton<T>(this T first) {
yield return first;
}
public static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> elements, int k) {
return k == 0 ? new[] { new T[0] } :
elements.SelectMany((e, i) =>
elements.Skip(i + 1).Combinations(k - 1).Select(c => (new[] { e }).Concat(c)));
}
然后您只需生成组合并过滤:
var ans = Enumerable.Range(1, Flights.Length)
.SelectMany(k => Flights.Combinations(k))
.Where(fs => fs.Count() == 1 || fs.Where(f1 => fs.Any(f2 => f1.Destination == f2.Origin)).Count() == fs.Count() - 1)
.Where(fs => fs.Any(f => f.Origin == SearchingOrigin) && fs.Any(f => f.Destination == SearchingDestination))
.GroupBy(fs => fs.Where(f => f.Origin == SearchingOrigin).First())
.Select(fsg => fsg.Key.AsSingleton().Concat(fsg.SelectMany(fs => fs.Except(fsg.Key.AsSingleton()))).ToList())
.ToList();
答案 1 :(得分:0)
一种选择是在细分中构建图形,并遍历所有组合/路径/行程。
在某种程度上类似于第一种方法的另一种方法是迭代细分,.Push
每个细分到Stack
,找到下一个目的地,递归< / em>,一旦没有更多关联的目标要评估,请确保当前段为.Pop
(见下文)。
public class Segment
{
public string Name { get; set; }
public string Origin { get; set; }
public string Destination { get; set; }
public string Flight { get; set; }
}
public class Analyzer
{
public Analyzer(IEnumerable<Segment> segments)
{
Segments = segments;
}
protected IEnumerable<Segment> Segments { get; set; }
public IEnumerable<IEnumerable<Segment>> Process(IEnumerable<Segment> origins = null, Stack<Segment> current = null)
{
if (origins == null)
origins = Segments;
if (current == null)
current = new Stack<Segment>();
foreach (var origin in origins)
{
current.Push(origin);
var destinations = Segments.Where(p => p.Origin == origin.Destination);
if (destinations.Any())
{
foreach (var child in Process(destinations, current))
{
yield return child;
};
}
else
{
yield return current.Reverse().ToList();
}
current.Pop();
}
}
}
这将为您提供所有行程(段组)组合
var itineraries = new Analyzer(segments).Process();
但是你提到你希望它们按初始航班分组,因为同一行程可能有很多变种,这是完全有道理的
var query = from itinerary in itineraries
let first = itinerary.First()
let last = itinerary.Last()
where trip.Origin == first.Origin
&& trip.Destination == last.Destination
group itinerary by first.Flight into groupings
select groupings
.SelectMany(p => p)
.Distinct();
这应该会给你预期的结果
注意:当然,迭代这种方式并在进行递归时会产生成本,如果图表非常深,可能会有一些性能损失,但在讨论航段时,则越少越好:)