이 데이터를 C# (LINQ?)로 변환하는 가장 쉬운 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/1007290

  •  06-07-2019
  •  | 
  •  

문제

이 예제 데이터가 주어지면 (PO, SKU, QTY는 속성이있는 .NET 클래스에서) :

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가있는 고정 열 형식으로 변환해야합니다 (필요한 경우> 5에 필요한 경우 PO를 반복) :

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 클래스 일 수 있습니다. PO로 그룹화 한 다음 5의 카운트로 LINQ 에서이 작업을 수행하는 간단한 방법이 있습니까?

편집 : 대상 형식을 제어 할 수 없습니다. 그리고 관심있는 사람이라면 누구나 Vendornet과 Vendorbridge 가이 말도 안되는 것을 필요로합니다.

도움이 되었습니까?

해결책

첫째, 다음은 객체의 올바른 계층 구조를 생성하는 쿼리가 있습니다. 익명 유형을 사용하고 있지만 자신의 적절한 클래스를 사용하기 위해 쉽게 변경할 수 있습니다.

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

제 생각에는 LINQ를 사용하지 않고 CSV를 생성하면 코드가 훨씬 더 읽을 수 있습니다.

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

다른 팁

당신은 간다. 나는 당신이 원하는 방식으로 출력을 포맷하지 않았습니다. 그러나 이것은 행을 피벗하는 방법에 대한 아이디어를 제공해야합니다. 도움이 되었기를 바랍니다 :-)

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},
                       };
        }
 }

편집 : Luke의 의견을 바탕으로 쿼리를 수정했습니다.

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 + ","))
                        });
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top