2009-06-22 17 views
6

Giải pháp nào được ưu tiên?Câu lệnh C# Linq hoặc foreach() cho tổng số tập hợp con?

Đối với một danh sách:

List<ExampleInfo> exampleList = new List<ExampleInfo>(); 

public class ExampleInfo 
{ 
    internal ExampleInfo() 
    { } 
    /* Business Properties */ 
    public int Id { get; set; } 
    public string Type { get; set; } 
    public decimal Total { get; set; } 
} 

Tôi muốn để có được tổng số phụ dựa off the 'Tổng' giá trị.

Lựa chọn 1:

var subtotal1 = exampleList.Where(x => x.Type == "Subtype1").Sum(x => x.Total); 
var subtotal2 = exampleList.Where(x => x.Type == "Subtype2").Sum(x => x.Total); 

Phương án 2:

decimal subtotal1 = 0m; 
decimal subtotal2 = 0m; 
foreach (ExampleInfo example in exampleList) 
{ 
    switch (example.Type) 
    { 
     case "Subtype1": 
      subtotal1 += example.Total; 
      break; 
     case "Subtype2": 
      subtotal2 += example.Total; 
      break; 
     default: 
      break; 

    } 
} 

Danh sách này sẽ được < 10 mặt hàng ở hầu hết các trường hợp.

Chỉnh sửa: Chris đã nêu lên một điểm rất hay mà tôi không đề cập đến. Chương trình đã sử dụng .NET Framework 3.5 SP1 nên khả năng tương thích không quan trọng ở đây.

Trả lời

4

Cả hai ví dụ này đều có mã trùng lặp và cả hai đều không sẵn sàng để thay đổi trên Type - điều gì sẽ xảy ra nếu nó có ba giá trị? Nếu nó có 30 thì sao?
Bạn có thể sử dụng LINQ để nhóm của nó và nhận được tổng số:

var totals = from p in exampleList 
      group p by p.Type into g 
      select new { Type = g.Key, Total = g.Sum(p => p.Total) }; 

Vì vậy totals là một bộ sưu tập của các đối tượng với các thuộc tính TypeTotal

+0

Chính xác những gì tôi đã bận rộn gõ cùng một lúc :) –

+0

ha tôi chỉ cần gõ tương đương chức năng –

2

Tôi không nghĩ rằng sẽ có nhiều sự khác biệt về hiệu suất cho các danh sách nhỏ như vậy.

Tùy chọn 1 sẽ lặp qua danh sách hai lần trong khi Tùy chọn 2 chỉ lặp qua danh sách một lần. Điều đó có thể quan trọng hơn cần lưu ý đối với các danh sách lớn hơn các danh sách nhỏ hơn.

Tùy chọn 1 dễ đọc hơn, nhưng tôi chắc chắn sẽ đảm bảo đưa ra nhận xét rằng nó lặp lại qua danh sách hai lần.

Lợi thế hiển nhiên đối với Tùy chọn 2 là mã hoạt động trong .NET Framework 2.0. Sử dụng LINQ có nghĩa là ứng dụng của bạn yêu cầu .NET Framework 3.5.

5

Bất kể kích thước danh sách, nếu bạn đang nhắm mục tiêu .NET 3.5 Tôi sẽ sử dụng LINQ, nếu chỉ để dễ đọc.

Tôi là một người hâm mộ tuyệt vời viết những gì bạn muốn nói, chứ không phải cách nó được thực hiện và LINQ làm điều này rất dễ dàng trong những trường hợp như vậy.

Bạn thậm chí có thể kéo các phép tính vào một câu lệnh LINQ duy nhất, nhóm theo Loại. Bằng cách đó bạn sẽ không phải hai vòng cho LINQ nhưng chỉ có một như trong ví dụ thứ hai:.

var subtotals = from x in exampleList 
       group x by x.Type into g 
       select new { Type = x.Key, SubTotal = g.Sum(x => x.Total) }; 

(Không hoàn toàn chắc chắn cho dù các mã hoạt động như nó, nó chỉ là một thích ứng nhanh chóng từ một trong những 101 LINQ Samples Cú pháp nên là ok, mặc dù.)

1

Đối với tùy chọn1, nội bộ vòng lặp foreach sẽ được thực thi hai lần bởi hàm thời gian chạy C#. Do đó, loại xử lý sẽ nhiều hơn. Nhưng đối với < 10 mục, nó hầu như không tạo ra bất kỳ sự khác biệt nào và tùy chọn 1 có vẻ dễ đọc hơn. Tôi sẽ đi với tùy chọn 1 cho < 10 mục.

+0

Các biên dịch C# không thực hiện vòng lặp ở tất cả. Nó được thực hiện tại thời điểm thực hiện. –

+0

Cảm ơn Jon. Thay đổi 'trình biên dịch' thành 'thời gian chạy env'. –

4

Lựa chọn 3

var groupings = exampleList 
    .GroupBy(x => x.Type, x => x.Total) 
    .Select(x => new { Type = x.Key, SubTotal = x.Sum() }); 

Bạn sẽ có một danh sách các lớp như sau:

class <Anonymous> 
{ 
    public string Type { get; }  
    public decimal SubTotal { get; } 
} 

liệt kê và gán cho giá trị thích hợp, mặc dù nó có thể là quá mức cần thiết cho một nhóm nhỏ như vậy.

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