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)
tandai pandai besi
sumber

Jawaban:

320

Gunakan Any()alih-alih Contains():

buildingStatus.Any(item => item.GetCharValue() == v.Status)
Rex M
sumber
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)
flq
sumber
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.

Otak Lunak
sumber
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.

XXXXX
sumber
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;
}
psabela
sumber
-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