2012-01-24 5 views
2

Это LINQ и лямбда-выражения убивают меня, так что я снова ищет помощи здесь :)Split список несколькими условиями

То, что я хотел бы сделать, это преобразование List<Order> в List<List<Order>> имея несколько вещей на виду.

Существует некоторый класс Order с идентификатором, валютой и 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, который представляет один элемент выходного преобразования несколько строк вверх, но вместе со списком имеет индекс свойств.

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 заранее :)

ответ

4

Это в основном @ ответ BrokenGlass в добавление к GroupBy и SelectMany для полноты:

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) в начале запроса. Но в вашем тестовом примере это не имеет значения.

+0

Очень приятно! Вам нужно переименовать внутренний 'g' в свой' SelectMany', потому что он конфликтует с внешним 'g' и удаляет дополнительный') 'в конце' OrderList = g.Select (x => x.Order). ToList()) 'для компиляции. Но кроме этих простых опечаток он дает правильные результаты. – dasblinkenlight

+0

Спасибо за указание. Я исправил эти опечатки. – pad

+0

Вот и все. Большое спасибо! Теперь я должен понять, что действительно происходит в этом запросе и как у вас есть правильный результат :) – 100r

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(); 
+0

Возможно, вам нужно добавить сортировочную часть для полноты. – pad

+0

ах я пропустил эту часть, многоуровневый порядок сложнее – BrokenGlass

+0

Сортировка по 'Currency' first и' ID', кажется, достаточно. – pad

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; 
Смежные вопросы