按多个条件拆分列表

时间:2012-01-24 20:45:54

标签: c# linq lambda

这个LINQ和lambda表达式正在杀死我,所以我再次在这里寻求帮助:)

我想做的是将List<Order>转换为List<List<Order>>,并考虑到一些事情。

有一些类Order具有ID,货币和Ammount,其中仅基本货币在此问题中有一定的作用。

class Order
{
    int ID;
    string Currency;
    money Ammount
}

Order类旁边,列表的最大大小有一些参数。

int MaxListSize = 3;

还有订单清单

List<Order>
{
    1, EUR, 100
    2, EUR, 200
    3, USD, 34
    4, EUR, 12
    5, EUR, 54
    6, USD, 67
    7, EUR, 22
    8, USD, 67
    9, EUR, 89
    10, USD, 64
    11, EUR, 45
    12, USD, 65
    13, USD, 2
    14, EUR, 78
    15, USD, 79
    16, USD, 66
    17, EUR,  3
    18, EUR, 2
}

转型应该是这样的

List<List<Order>>
{
    {1, EUR, 100},  {2, EUR, 200}   {4, EUR, 12}
    {5, EUR, 54},   {7, EUR, 22},   {9, EUR, 89}
    {11, EUR, 45},  {14, EUR, 78},  {17, EUR,  3}
    {18, EUR, 2}
    {3, USD, 34},   {6, USD, 67},   {8, USD, 67}
    {10, USD, 64},  {12, USD, 65},  {13, USD, 2}
    {15, USD, 79},  {16, USD, 66}
}

翻译成简单语言此输出列表的每个元素sholud是仅包含相同货币的订单的列表,并且元素列表的最大大小应该是从开始的MaxListSize的参数。

当我在这里时,让我们再添加一点。让我们假设我们有一些类OrderGroup,表示一行输出转换几行uper,但与List一起它有属性索引。

class OrderGroup
{
    List<Order> OrderList
    int ListIndex
}

输出应该是

List<OrderGroup>
{
     GroupOrder {OrderList = new List<Order> {{1, EUR, 100},    {2, EUR, 200}   {4, EUR, 12}}, ListIndex  = 1}
     GroupOrder {OrderList = new List<Order> {{5, EUR, 54}, {7, EUR, 22},   {9, EUR, 89}},  ListIndex  = 2}
     GroupOrder {OrderList = new List<Order> {{11, EUR, 45},    {14, EUR, 78},  {17, EUR,  3}}, ListIndex  = 3}
     GroupOrder {OrderList = new List<Order> {{18, EUR, 2}}, ListIndex  = 4}
     GroupOrder {OrderList = new List<Order> {{3, USD, 34}, {6, USD, 67},   {8, USD, 67}}, ListIndex  = 1}
     GroupOrder {OrderList = new List<Order> {{10, USD, 64},    {12, USD, 65},  {13, USD, 2}}, ListIndex  = 2}
     GroupOrder {OrderList = new List<Order> {{15, USD, 79},    {16, USD, 66}}, ListIndex  = 3}
}

输出与第一个基本相同,加上有索引,应该取决于货币。每种货币都有自己的零基指数。

任何帮助都会被高估。我知道它应该用Select()或SelectMany()扩展方法完成,但我不知道如何。

提前Thanx:)

3 个答案:

答案 0 :(得分:4)

这基本上是@ BrokenGlass的答案,为完整性添加GroupBySelectMany

var results = orders.GroupBy(o => o.Currency)
                    .SelectMany(g => g.Select((order, index) => new { Index = index, Order = order })
                                      .GroupBy(x => x.Index / MaxListSize)
                                      .Select(og => new OrderGroup() 
                                      {
                                         ListIndex = og.Key,
                                         OrderList = og.Select(x => x.Order).ToList()
                                       })
                                      .ToList())
                    .ToList();

为了确保一般情况下的正确顺序,您可以在查询开头添加.OrderBy(o => o.ID)子句。但是在您的测试示例中无关紧要。

答案 1 :(得分:2)

要对列表进行分组,这样的事情应该有效:

var orderGroups = orders.Select((order, index) => new { Index = index, Order = order })
                        .GroupBy(x => x.Index / MaxListSize)
                        .Select(g => g.Select(x => x.Order).ToList())
                        .ToList();

转换为OrderGroup现在很简单:

var orderGroups = orders.Select((order, index) => new { Index = index, Order = order })
                        .GroupBy(x => x.Index / MaxListSize)
                        .Select(g => new OrderGroup() 
                         {
                            ListIndex = g.Key,
                            OrderList = g.Select(x => x.Order).ToList())
                         })
                        .ToList();

答案 2 :(得分:2)

这是一个棘手的选择,但它可以满足你的需要:

var res = orders
    .GroupBy(o => o.Currency)
    .SelectMany(g => g.Select((o,i) => new {Ind = i, Order = o}))
    .GroupBy(p => new { Num = p.Ind/3, Curr = p.Order.Currency })
    .Select(g => new OrderGroup {ListIndex = g.Key.Num, OrderList = g.Select(x => x.Order).ToList()})
    .ToList();
foreach (var list in res) {
    Console.Write(list.ListIndex);
    foreach (var order in list.OrderList) {
        Console.Write("   {0} {1} {2};", order.ID, order.Currency, order.Ammount);
    }
    Console.WriteLine();
}

运行它会产生以下输出:

0   1 EUR 100;   2 EUR 200;   4 EUR 12;
1   5 EUR 54;   7 EUR 22;   9 EUR 89;
2   11 EUR 45;   14 EUR 78;   17 EUR 3;
3   18 EUR 2;
0   3 USD 34;   6 USD 67;   8 USD 67;
1   10 USD 64;   12 USD 65;   13 USD 2;
2   15 USD 79;   16 USD 66;
相关问题