LINQ: ăn có một số truy vấn và Lambda


168

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

Có một số cách để làm điều này, dọc theo dòng mã (không biên dịch) dưới đây?

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

Câu trả lời:


320

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

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

13
Đẹp. Tôi cứ tự hỏi tại sao trên Trái đất Linq không cung cấp một Contains()phương pháp, và rồi tôi nhận ra rằng nó đáng lẽ phải Any()thay thế. +1
Nolonar

38

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

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

4

Đâ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) cái này sẽ trả về giá trị Boolean.


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

tạo ra 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à tạo ra cùng một đầu ra:

    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 phương thức mở rộng này để chuyển đổi một IEnumerable sang một cái khác, nhưng tôi không chắc nó hiệu quả đến mức 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 thành:

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

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


Cảm ơn larry đã hoạt động, đây là những gì tôi đã làm bằng cách tham khảo mã của bạn ... Nhưng sẽ rất tuyệt 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à 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 var statusStringList = Building.ToList (). Convert ALL <char> (st => st.GetCharValue ()); var test = from v in qry trong đó statusStringList.Contains (v.Status) chọn v; Tất cả các công việc, như tôi nói sẽ tốt hơn nếu không phải lập một danh sách mới hoặc sử dụng lambda bên trong Chứa nhưng xuất hiện KHÔNG THỂ?
đánh dấu smith

Tôi giả sử thuộc tính trạng thái là một chuỗi; do đó bạn phải chuyển đổi các trạng thái enums 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 khi bắt đầu và được thực hiện với nó.
XXXXX

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

-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 Toà nhà // giá trị ký tự //, trạng thái có tồn tại trong danh sách BuildingStatus // enum value //)

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

-1; trong khi chỉnh sửa của tôi cho câu hỏi đã làm mất hiệu lực câu trả lời này bằng cách xóa tất cả các tham chiếu Buildingkhỏi câu hỏi, điều này đã thực sự bị phá vỡ . foreach(Enum value in Enum.GetValues(typeof(buildingStatus)))là vô nghĩa.
Đánh dấu Amery
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.