LINQ: "berisi" dan permintaan Lambda


168

Saya telah a List<BuildingStatus>disebut buildingStatus. Saya ingin memeriksa apakah ini berisi status yang kode arang (dikembalikan oleh GetCharCode()) sama dengan beberapa variabel v.Status,.

Apakah ada cara untuk melakukan ini, di sepanjang baris kode (non-kompilasi) di bawah ini?

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

Jawaban:


320

Gunakan Any()alih-alih Contains():

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

13
Bagus. Saya terus bertanya-tanya mengapa di Bumi Linq tidak menyediakan Contains()metode, dan kemudian saya menyadari itu seharusnya Any(). +1
Nolonar

38

Metode ekstensi Linq Apa saja bisa bekerja untuk Anda ...

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

4

Inilah cara yang dapat Anda gunakan Containsuntuk mencapai apa yang Anda inginkan:

buildingStatus.Select(item => item.GetCharValue()).Contains(v.Status) ini akan mengembalikan nilai Boolean.


3

Saya tidak yakin persis apa yang Anda cari, tetapi program ini:

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

menghasilkan output yang diharapkan:

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

Program ini membandingkan representasi string dari enum dan menghasilkan output yang sama:

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

Saya membuat metode ekstensi ini untuk mengkonversi satu IEnumerable ke yang lain, tapi saya tidak yakin seberapa efisiennya; mungkin hanya membuat daftar di belakang layar.

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

Kemudian Anda dapat mengubah klausa tempat ke:

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

dan lewati membuat List<string>dengan ConvertAll ()di awal.


Terima kasih larry yang bekerja, ini yang saya lakukan dengan merujuk kode Anda ... Tapi alangkah baiknya jika memungkinkan jika saya tidak harus membuat daftar baru ???? // Digunakan ToList karena ini adalah ILIST dan jalankan GetCharValue saya // ini menghasilkan daftar "BARU" dengan status char saya charStringList = building.ToList (). ConvertAll <char> (st => st.GetCharValue ()); var test = dari v in qry di mana statusStringList.Contains (v.Status) pilih v; Semua berfungsi, seperti yang saya katakan akan lebih baik tidak harus melakukan daftar baru atau menggunakan lambda di dalam Berisi tetapi tampaknya TIDAK mungkin?
tandai smith

Saya menganggap properti status adalah string; Oleh karena itu Anda harus mengonversi status enums ke string untuk setiap perbandingan. Anda mungkin harus mengonversinya sekali di awal dan selesai melakukannya.
XXXXX

Saya telah mengedit yang menyederhanakan pertanyaan secara signifikan, tetapi dengan melakukan hal itu, jawaban semacam ini tidak valid. Maaf tentang itu, tapi saya pikir itu untuk keseluruhan yang lebih baik.
Mark Amery

-1

Jika saya mengerti dengan benar, Anda perlu mengonversi tipe (nilai char) yang Anda simpan di daftar Bangunan ke tipe (enum) yang Anda simpan di daftar buildingStatus.

(Untuk setiap status dalam daftar Bangunan // nilai karakter //, apakah status ada di daftar 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; sementara edit saya untuk pertanyaan telah sedikit membatalkan jawaban ini dengan menghapus semua referensi Buildingdari pertanyaan, ini sudah benar-benar rusak . foreach(Enum value in Enum.GetValues(typeof(buildingStatus)))adalah omong kosong.
Mark Amery
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.