2010-06-18 25 views
11

cách dễ nhất và phần nào hiệu quả để chuyển đổi một cấu trúc phẳng là gì:LINQ: Chuyển đổi cơ cấu phẳng để thứ bậc

object[][] rawData = new object[][] 
{ 
    { "A1", "B1", "C1" }, 
    { "A1", "B1", "C2" }, 
    { "A2", "B2", "C3" }, 
    { "A2", "B2", "C4" } 
    // .. more 
}; 

thành một cấu trúc thứ bậc:

class X 
{ 
    public X() 
    { 
    Cs = new List<string>(); 
    } 
    public string A { get; set; } 
    public string B { get; set; } 
    public List<string> Cs { get; private set; } 
} 

kết quả sẽ giống như

này
// pseudo code which describes structure: 
result = 
{ 
    new X() { A = "A1", B = "B1", Cs = { "C1", "C2" } }, 
    new X() { A = "A2", B = "B2", Cs = { "C3", "C4" } } 
} 

Tốt hơn là sử dụng các phương pháp mở rộng LINQ. Mục tiêu lớp X có thể được thay đổi (ví dụ: một công khai setter cho Danh sách), chỉ khi không thể/hữu ích như bây giờ.

+0

bạn cần một số loại nhóm bởi – Andrey

+0

@Andrey, vâng, đó là một nhóm bởi 'A' và' b' và tổng hợp các 'Cs' vào một danh sách. –

Trả lời

7

đối với trường hợp đặc biệt này:

.GroupBy(x => new { a = x[0], b = x[1] }) 
    .Select(x => new { A = x.Key.a, B = x.Key.b, C = x.Select(c => c[2]) }) 
+0

cho hệ thống phân cấp ví dụ của mình: '.Select (x => new X {A = x.Key.a, B = x.Key.b, Cs = x.Select (c => c [2]) .ToList ()}) ' –

+1

Tôi đang bối rối vì C = x.Select ... Điều này thực sự làm việc như thế này? Phải thử. –

+0

Vâng, nó hoạt động, nó thực sự là cách sử dụng cơ bản của 'GroupBy'. Cảm ơn rất nhiều. –

2

Something như thế này nên làm việc nếu chiều sâu của hệ thống cấp bậc của bạn bị hạn chế (như trong ví dụ của bạn, nơi bạn chỉ có ba cấp độ A, B và C). Tôi đơn giản X của bạn một chút:

class X { 
    public string A { get; set; } 
    public string B { get; set; } 
    public List<string> Cs { get; set; } 
} 

Sau đó, bạn có thể sử dụng lồng nhau GroupBy nhiều lần như bạn cần (tùy thuộc vào độ sâu của hệ thống phân cấp). Nó sẽ là cũng tương đối dễ dàng để viết lại này thành một phương pháp đệ quy (mà có thể làm việc cho hệ thống phân cấp tùy tiện sâu):

// Group by 'A' 
rawData.GroupBy(aels => aels[0]).Select(a => 
    // Group by 'B' 
    a.GroupBy(bels => bels[1]).Select(b => 
    // Generate result of type 'X' for the current grouping 
    new X { A = a.Key, B = b.Key, 
      // Take the third element 
      Cs = b.Select(c => c[2]).ToList() })); 

Đây là chi tiết rõ ràng hơn so với các giải pháp khác ở đây, nhưng có lẽ nó sẽ được dễ đọc hơn vì nó là mã hóa đơn giản hơn của ý tưởng ...

1

với các thành viên X là chuỗi và Cs là một tập tin, và rawData là một mảng của mảng của các đối tượng, tôi sẽ thêm một constructor X public X(string a, string b, List<string> cs) và sau đó thực hiện mã này

var query = from row in rawData 
      group row by new { A = row[0], B = row[1] } into rowgroup 
      select new X((string)rowgroup.Key.A, (string)rowgroup.Key.B, rowgroup.Select(r => (string)r[2]).ToList()); 

Đây là dữ liệu thô sau

object[][] rawData = new object[][] 
    { 
     new object[] { "A1", "B1", "C1" }, 
     new object[] { "A1", "B1", "C2" }, 
     new object[] { "A2", "B2", "C3" }, 
     new object[] { "A2", "B2", "C4" } 
     // .. more 
    }; 
+0

Cảm ơn. Tôi đã thực hiện một hàm tạo như thế này (nhưng với một IEnumerable thay vì Danh sách, sao chép nó vào một mảng nội bộ). Các truy vấn cũng có vẻ tốt, tôi chỉ quen thuộc hơn với các phương pháp mở rộng. Tôi chấp nhận câu trả lời của Andrey bởi vì anh ta là người đầu tiên với câu trả lời đúng (về cơ bản). –

0

Tôi muốn xem liệu tôi có thể viết điều này mà không có trường hợp ẩn danh hay không. Đó không phải là quá xấu:

IEnumerable<X> myList = 
    from raw0 in rawData 
    group raw0 by raw0[0] into g0 
    let g1s = 
    (
    from raw1 in g0 
    group raw1 by raw1[1] 
) 
    from g1 in g1s 
    select new X() 
    { 
    A = g0.Key, 
    B = g1.Key, 
    C = g1.Select(raw2 => raw2[2]).ToList() 
    } 
+0

Giải pháp thú vị. Bạn cũng có thể sử dụng một 'KeyValuePair ' chỉ cho hai khóa. –

+0

@David B: 'g0.Key' không hoạt động. Hãy giúp tôi. – FMFF

Các vấn đề liên quan