2009-06-13 32 views
9

Tôi có một bộ sưu tập các đối tượng thuộc một loại mà tôi muốn chuyển đổi thành một loại khác. Điều này có thể được thực hiện dễ dàng với foreach, nhưng tôi muốn tìm ra cách sử dụng hàm tổng hợp của LINQ để làm điều đó.Cách thêm vào danh sách bằng chức năng tổng hợp của LINQ C#

Vấn đề là tất cả các ví dụ tổng hợp sử dụng loại chuỗi hoặc int, hỗ trợ toán tử '+'. Tôi muốn có loại accumulator là một danh sách, không hỗ trợ ngữ nghĩa '+'.

Dưới đây là một ví dụ nhanh:

public class DestinationType 
{ 
    public DestinationType(int A, int B, int C) { ... } 
} 

var set = from item in context.Items 
      select new { item.A, item.B, item.C }; 

var newSet = set.Aggregate(new List<DestinationType>(), 
          (list, item) => list.Add(new DestinationType(item.A, item.B, item.C))); 

Vấn đề là Danh sách <> .Add trả về void. Kiểu trả về của tham số thứ hai để tổng hợp cần phải là một List.

Nếu tôi có một loại danh sách đó được hỗ trợ '+' loại ngữ nghĩa tôi chỉ có thể làm cho tham số thứ hai

list + item 

Tuy nhiên tôi không thể tìm thấy bất kỳ loại bộ sưu tập có hỗ trợ loại điều.

Có vẻ như điều này có thể dễ dàng thực hiện được trong LINQ. Là có một cách? Ngoài ra, nếu tôi đang thiếu một cách hoàn toàn dễ dàng hơn, tôi cũng muốn tìm hiểu về điều đó. Cảm ơn!

+0

Cảm ơn bạn cho tất cả các câu trả lời tuyệt vời! Câu trả lời của Sam & Talljoe thực hiện điều này đơn giản nhất khi sử dụng LINQ. Thx lần nữa! – Slaggg

Trả lời

9

Tôi nghĩ cuộc gọi đến Select kết hợp với ToList() có thể là những gì bạn cần tại đây. Ví dụ:

context.Items 
    .Select(item => new DestinationType(item.A, item.B, item.C)) 
    .ToList(); 
23

Giả sử đây là LINQ to Objects, hãy thử ...

var newSet = set.Aggregate(new List<DestinationType>(), 
            (list, item) => 
            { 
             list.Add(new DestinationType(item.A, item.B, item.C)); 
             return list; 
            }); 
+0

Đây là cách phù hợp để thực hiện. – mquander

+0

Điều này cũng làm việc cho tôi khi sử dụng Union trong phần Func –

4

Bạn chỉ có thể áp dụng select đây.

var newSet = set.Select(item => new DestinationType(...)).ToList(); 

Aggregate (thường được gọi là fold hoặc reduce) được sử dụng để kết hợp yếu tố cùng nhau nơi select áp dụng một chức năng để mỗi phần tử.

Ex:

Hãy f là một hàm unary, sau đó [a, b, c].select(f) bằng [f(a), f(b), f(c)].

Gọi f là hàm nhị phân, sau đó [a, b, c].aggregate(f, init) bằng f(a, f(b, f(c, init))).

Cách bạn chọn trong ví dụ của bạn là không phổ biến trong C# nhưng thường được sử dụng trong lập trình chức năng mà danh sách (liên kết) được chuyển thành danh sách mới thay vì thay đổi một bộ sưu tập hiện có:

reversed = fold (\list element -> element:list) [] [1..10] 

Nếu bạn thực sự muốn thực hiện tính toán này với aggregate, sử dụng giải pháp của Dustin hoặc thực hiện tốt hơn loại liên kết dựa trên danh sách cho các bộ sưu tập không thay đổi (thậm chí bạn có thể cung cấp loại này là operator +).

3
list.AddRange(context.Items.Select(item => 
    new DestinationType(item.A, item.B, item.C)); 

Tôi nhận thấy nó không sử dụng chức năng Tổng hợp, nhưng có lẽ bạn nên tìm một ví dụ tốt hơn để tìm hiểu tổng hợp.

1

Trừ khi tôi là thiếu một cái gì đó rõ ràng, tại sao không chỉ làm:

public class DestinationType 
{ 
    public DestinationType(int A, int B, int C) { ... } 
} 

var newSet = from item in context.Items 
    select new DestinationType(item.A, item.B, item.C); 
Các vấn đề liên quan