如何分组展平列表

时间:2016-04-26 08:25:48

标签: c# linq group-by flatten

我的飞行课程如下:

public class Flight{     
     public string From {get;set;}
     public string To {get;set;}
}

我已经展平了飞行列表,其中包含航班(注意:航班n可能有n从 - 到

var listOfFromTo = new List<Flight>{

new Flight{ From = "A", To="B"},
new Flight{ From="B", To="C"},

new Flight{ From="D", To="E"},
new Flight{ From="E", To="F"},
new Flight{ From="F", To="G"}   

//new Flight {From="...", To="..."}
};

我想要的是:

var listOfListOfFlights = new List<List<Flight>>(){flight1, flight2};

航班1和航班2是

var flight1 = new List<Flight>{
    new Flight{ From="A", To="B"},      
    new Flight{ From="B", To="C"}       
};


var flight2 = new List<Flight>{
    new Flight{ From="D", To="E"},
    new Flight{ From="E", To="F"},
    new Flight{ From="F", To="G"}   
};

我无法弄清楚如何做到这一点,但我猜我应该以某种方式使用组

var result1 =
    from loft in listOfFromTo
    group loft by new { loft.From, loft.To }
        into r
        select new Flight {
            From = r.Key.From,
            To = r.Key.To
        };

编辑我想在linqpad中分享@ bit&#s算法的结果:

enter image description here

1 个答案:

答案 0 :(得分:2)

根据评论,您需要对Flight课程进行一些修改,以适应指示新路线的子航班。 这是更新Flight

public class Flight
{
    public string From { get; set; }
    public string To { get; set; }

    // Sub routes
    public List<Flight> Flights { get; set; }
}

以下是该方法的粗略草稿,它采用输入fromto以及list of all the flights并递归计算所需的路径

private List<Flight> GetRoute(string from, string to, IEnumerable<Flight> allFlights)
{
    // Check if the route already exists! 
    var desiredRoute = allFlights.FirstOrDefault(r => r.From == from && r.To == to);
    if (desiredRoute != null)
    {
        return desiredRoute.Flights ?? new List<Flight> { desiredRoute };
    }

    // use inner join to find possible matches with the from and to with the currently available flights/routes
    var routes = allFlights.Join(allFlights, f1 => f1.To, f2 => f2.From, (f1, f2) =>
                            new Flight
                            {
                                // New route found
                                From = f1.From,
                                To = f2.To,

                                // sub Flights for the new route
                                Flights = new List<Flight> { f1, f2 }
                            }).ToList();

    // start a new search with the newly found routes
    return GetRoute(from, to, allFlights.Concat(routes));
}

以下是如何调用它:

var route = GetRoute("D", "G", listOfFromTo);

这是一个显示结果的片段:

foreach (var flight in routes)
{
    Console.WriteLine(flight.From + "=>" + flight.To);
}

请注意,您必须处理无法找到路由的情况,否则会导致堆栈溢出!