2009-10-14 31 views
121

Tôi có một số List<BuildingStatus> được gọi là buildingStatus. Tôi muốn kiểm tra xem nó có chứa một trạng thái có mã char (trả về bởi GetCharCode()) bằng một số biến, v.Status.LINQ: "chứa" và truy vấn Lambda

Có cách nào để thực hiện việc này, dọc theo các dòng của mã (không biên dịch) bên dưới không?

buildingStatus.Contains(item => item.GetCharValue() == v.Status) 

Trả lời

232

Sử dụng Any() thay vì Contains():

buildingStatus.Any(item => item.GetCharValue() == v.Status) 
+6

Tốt. Tôi cứ tự hỏi tại sao Earth Linq lại không cung cấp phương thức 'Contains()', và sau đó tôi nhận ra nó được cho là 'Any() 'thay thế. +1 – Nolonar

30

Phương pháp LINQ mở rộng Bất kỳ có thể làm việc cho bạn ...

buildingStatus.Any(item => item.GetCharValue() == v.Status) 
3

Tôi không chắc chắn chính xác những gì bạn' đang tìm kiếm, nhưng chương trình này:

public class Building 
    { 
     public enum StatusType 
     { 
      open, 
      closed, 
      weird, 
     }; 

     public string Name { get; set; } 
     public StatusType Status { get; set; } 
    } 

    public static List <Building> buildingList = new List<Building>() 
    { 
     new Building() { Name = "one", Status = Building.StatusType.open }, 
     new Building() { Name = "two", Status = Building.StatusType.closed }, 
     new Building() { Name = "three", Status = Building.StatusType.weird }, 

     new Building() { Name = "four", Status = Building.StatusType.open }, 
     new Building() { Name = "five", Status = Building.StatusType.closed }, 
     new Building() { Name = "six", Status = Building.StatusType.weird }, 
    }; 

    static void Main (string [] args) 
    { 
     var statusList = new List<Building.StatusType>() { Building.StatusType.open, Building.StatusType.closed }; 

     var q = from building in buildingList 
       where statusList.Contains (building.Status) 
       select building; 

     foreach (var b in q) 
      Console.WriteLine ("{0}: {1}", b.Name, b.Status); 
    } 

sản xuất sản lượng dự kiến:

one: open 
two: closed 
four: open 
five: closed 

chương trình này so sánh một chuỗi đại diện của enum và sản xuất cùng một sản lượng:

public class Building 
    { 
     public enum StatusType 
     { 
      open, 
      closed, 
      weird, 
     }; 

     public string Name { get; set; } 
     public string Status { get; set; } 
    } 

    public static List <Building> buildingList = new List<Building>() 
    { 
     new Building() { Name = "one", Status = "open" }, 
     new Building() { Name = "two", Status = "closed" }, 
     new Building() { Name = "three", Status = "weird" }, 

     new Building() { Name = "four", Status = "open" }, 
     new Building() { Name = "five", Status = "closed" }, 
     new Building() { Name = "six", Status = "weird" }, 
    }; 

    static void Main (string [] args) 
    { 
     var statusList = new List<Building.StatusType>() { Building.StatusType.open, Building.StatusType.closed }; 
     var statusStringList = statusList.ConvertAll <string> (st => st.ToString()); 

     var q = from building in buildingList 
       where statusStringList.Contains (building.Status) 
       select building; 

     foreach (var b in q) 
      Console.WriteLine ("{0}: {1}", b.Name, b.Status); 

     Console.ReadKey(); 
    } 

Tôi tạo ra phương pháp mở rộng này để chuyển đổi một IEnumerable khác, nhưng tôi không chắc nó hiệu quả như thế nào; nó chỉ có thể tạo ra một danh sách đằng sau hậu trường.

public static IEnumerable <TResult> ConvertEach (IEnumerable <TSource> sources, Func <TSource,TResult> convert) 
{ 
    foreach (TSource source in sources) 
     yield return convert (source); 
} 

Sau đó, bạn có thể thay đổi mệnh đề where to:

where statusList.ConvertEach <string> (status => status.GetCharValue()). 
    Contains (v.Status) 

và bỏ qua việc tạo ra các List<string> với ConvertAll() lúc đầu.

+0

Cảm ơn ấu trùng đã làm việc, đây là những gì tôi đã làm bằng cách tham khảo mã của bạn ... Nhưng nó sẽ là tốt đẹp nếu có thể nếu tôi không phải tạo một danh sách mới ???? // Được sử dụng ToList vì nó là một ILIST và chạy GetCharValue của tôi // điều này tạo ra một danh sách "MỚI" với char của tôi var statusStringList = building.ToList(). ConvertAll (st => st.GetCharValue()); var test = from v in qry nơi statusStringList.Contains (v.Status) chọn v; Tất cả các công trình, như tôi nói nó sẽ được tốt đẹp không phải làm một danh sách mới hoặc sử dụng một lambda bên trong Chứa nhưng xuất hiện của nó không thể? –

+0

Tôi giả định thuộc tính trạng thái là một chuỗi; do đó bạn phải chuyển đổi enums trạng thái thành chuỗi cho mỗi so sánh. Bạn cũng có thể chuyển đổi chúng một lần ngay từ đầu và được thực hiện với nó. – XXXXX

+0

Tôi đã thực hiện chỉnh sửa đơn giản hóa đáng kể câu hỏi nhưng, khi làm như vậy, sắp xếp không hợp lệ câu trả lời này. Xin lỗi về điều đó, nhưng tôi đoán nó là tốt hơn cho tổng thể. –

-1

Nếu tôi hiểu chính xác, bạn cần chuyển đổi loại (giá trị char) mà bạn lưu trữ trong danh sách Xây dựng thành loại (enum) mà bạn lưu trữ trong danh sách buildingStatus.

(Đối với mỗi trạng thái trong danh sách Building // nhân vật giá trị //, làm tình trạng tồn tại trong danh sách buildingStatus // giá trị enum //)

public static IQueryable<Building> WithStatus(this IQueryable<Building> qry, 
     IList<BuildingStatuses> buildingStatus) 
    { 
     return from v in qry 
       where ContainsStatus(v.Status) 
       select v;   
    } 


private bool ContainsStatus(v.Status) 
{ 
foreach(Enum value in Enum.GetValues(typeof(buildingStatus))) 
{ 
    If v.Status == value.GetCharValue(); 
    return true; 
} 
return false; 
} 
+0

-1; trong khi chỉnh sửa của tôi cho câu hỏi đã làm mất hiệu lực một chút câu trả lời này bằng cách xóa tất cả tham chiếu đến 'Tòa nhà' khỏi câu hỏi, điều này đã thực sự * bị hỏng *. 'foreach (Giá trị enum trong Enum.GetValues ​​(typeof (buildingStatus)))' là vô nghĩa. –

0

Đây là cách bạn có thể sử dụng để Contains đạt được những gì bạn muốn:

buildingStatus.Select(item => item.GetCharValue()).Contains(v.Status) điều này sẽ trả về giá trị Boolean.

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