Какой самый простой способ исправить эти данные в C # (linq?)? - PullRequest
0 голосов
/ 17 июня 2009

Учитывая данные этого примера (в классах .NET, где Po, Sku, Qty являются свойствами):

PO, Sku, Qty
1,ABC,1
1,DEF,2
1,GHI,1
1,QWE,1
1,ASD,1
1,ZXC,5
1,ERT,1
2,QWE,1
2,ASD,11
2,ZXC,1
3,ERT,1
3,DFG,1
3,DFH,1
3,CVB,4
3,VBN,1
3,NMY,1

Мне нужно преобразовать его в фиксированный формат столбца, максимум 5 SKU на строку (повторяя PO, если это необходимо для> 5):

PO, SkuA, QtyA, SkuB, QtyB, SkuC, QtyC, SkuD, QtyD, SkuE, QtyE
1, ABC, 1, DEF, 2, GHI, 1, QWE, 1, ASD, 1
1, ZXC, 5, ERT, 1, , , , , , 
2, QWE, 1, ASD, 11, ZXC, 1, , , , 
3, ERT, 1, DFG, 1, DFH, 1, CVB, 4, VBN, 1
3, NMY, 1, , , , , , , , 

Вывод может быть CSV (что я и выводю) или классы .NET - неважно, там. Есть ли простой способ сделать это в Linq, сгруппировав по PO, а затем по 5?

РЕДАКТИРОВАТЬ: я не могу контролировать формат назначения. И для тех, кто заинтересован, это VendorNet и VendorBridge, которые требуют этой ерунды.

Ответы [ 2 ]

1 голос
/ 17 июня 2009

Во-первых, вот запрос, который сгенерирует правильную иерархию объектов. Я использую анонимные типы, но достаточно легко изменить их на собственные классы.

var query = yourData
    .GroupBy
    (
        x => x.PO
    )
    .SelectMany
    (
        x => x.Select
        (
            (y, i) => new { y.PO, y.Sku, y.Qty, Key = i / 5 }
        )
    )
    .GroupBy
    (
        x => new { x.PO, x.Key }
    );

Использование LINQ для создания CSV из результатов запроса - это нечто вроде хака, но оно выполняет свою работу. («Преимущество» использования LINQ заключается в том, что вы можете при желании объединить исходный запрос и генерацию CSV в одно массивное утверждение.)

IEnumerable<string> csvLines = query
    .Select
    (
        x => x.Aggregate
        (
            new { Count = 0, SB = new StringBuilder() },
            (a, y) => new
            {
                Count = a.Count + 1,
                SB = ((a.SB.Length == 0) ? a.SB.Append(y.PO) : a.SB)
                    .Append(", ").Append(y.Sku).Append(", ").Append(y.Qty)
            },
            a => a.SB.ToString() + string.Join(", , ", new string[6 - a.Count])
        )
    );

string csv = string.Join(Environment.NewLine, csvLines.ToArray());

По моему мнению, создание CSV без использования LINQ делает код намного более читабельным:

StringBuilder sb = new StringBuilder();
foreach (var group in query)
{
    int count = 0;
    foreach (var item in group)
    {
        if (count++ == 0)
        {
            sb.Append(item.PO);
        }
        sb.Append(", ").Append(item.Sku).Append(", ").Append(item.Qty);
    }
    while (count++ < 5)
    {
        sb.Append(", , ");
    }
    sb.Append(Environment.NewLine);
}

string csv = sb.ToString();
0 голосов
/ 17 июня 2009

Вот, пожалуйста. Я не отформатировал вывод так, как вы хотели. Но это должно дать вам представление о том, как поворачивать строки. Надеюсь, это поможет: -)

public class MyClass
{
        public int PO { get; set; }
        public String SKU { get; set; }
        public int Qty { get; set; }

        public static IEnumerable<MyClass> GetList()
        {
            return new List<MyClass>()
                       {
                           new MyClass {PO = 1, SKU = "ABC", Qty = 1},
                           new MyClass {PO = 1, SKU = "DEF", Qty = 2},
                           new MyClass {PO = 1, SKU = "GHI", Qty = 1},
                           new MyClass {PO = 1, SKU = "QWE", Qty = 1},
                           new MyClass {PO = 1, SKU = "ASD", Qty = 1},
                           new MyClass {PO = 1, SKU = "ZXC", Qty = 5},
                           new MyClass {PO = 1, SKU = "ERT", Qty = 1},
                           new MyClass {PO = 2, SKU = "QWE", Qty = 1},
                           new MyClass {PO = 2, SKU = "ASD", Qty = 1},
                           new MyClass {PO = 2, SKU = "ZXC", Qty = 5},
                       };
        }
 }

РЕДАКТИРОВАТЬ: я исправил запрос на основе комментария Люка

var lQuery =
            MyClass.GetList()
                .GroupBy(pArg => pArg.PO)
                .Select(pArg => new
                   {
                       Test = pArg.Select((pArg1, pId) => 
                                          new {ID = (pId / 5), 
                                               pArg1.PO, pArg1.SKU, pArg1.Qty})
                                       .GroupBy(pArg1 => pArg1.ID)
                                       .Select(pArg1 => 
                                               pArg1.Aggregate(pArg.Key.ToString(),
                                                               (pSeed, pCur) => 
                                                               pSeed + pCur.SKU + ","))
                        });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...