LINQ: “içerir” ve bir Lambda sorgusu


168

Bir List<BuildingStatus>telefonum var buildingStatus. Char kodu (döndürülen GetCharCode()) bazı değişkene eşit olan bir durum içerip içermediğini kontrol etmek istiyorum v.Status.

Bunu (derleyici olmayan) kod satırları boyunca yapmanın bir yolu var mı?

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

Yanıtlar:


320

Şunun Any()yerine kullanın Contains():

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

13
Güzel. Earth Linq'te neden bir Contains()yöntem sağlamadığını merak ediyorum ve Any()bunun yerine bunun olması gerektiğini anladım . +1
Nolonar

38

Linq uzatma yöntemi Herhangi biri sizin için işe yarayabilir ...

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

4

Containsİstediğinizi elde etmek için nasıl kullanabileceğiniz aşağıda açıklanmıştır :

buildingStatus.Select(item => item.GetCharValue()).Contains(v.Status) bu bir Boolean değeri döndürür.


3

Tam olarak ne aradığınızdan emin değilim, ama bu program:

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

beklenen çıktıyı üretir:

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

Bu program, numaralandırma dizesinin temsilini karşılaştırır ve aynı çıktıyı üretir:

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

Bir IEnumerable diğerine dönüştürmek için bu uzantı yöntemi oluşturdu, ancak ne kadar verimli olduğundan emin değilim; sadece perde arkasında bir liste oluşturabilir.

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

Sonra where yan tümcesini şu şekilde değiştirebilirsiniz:

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

ve başında List<string>ile oluşturmayı atlayın ConvertAll ().


Çalıştığınız için teşekkürler larry, işte kodunuza başvurarak yaptım ... Ama yeni bir liste oluşturmak zorunda olmasaydım mümkünse güzel olurdu ???? // ToList kullanılır çünkü onun bir ILIST ve benim GetCharValue çalıştırmak // bu benim char var statStringList = building.ToList () ile bir "YENİ" listesi üretir. ConvertAll <char> (st => st.GetCharValue ()); var test = statusStringList.Contains (v.Status) 'u v / qry içinde v seçin; Dediğim gibi tüm işler, yeni bir liste yapmak veya içeride bir lambda kullanmak zorunda olmamak güzel olurdu İçeriyor ama onun mümkün DEĞİL görünüyor?
mark smith

Status özelliğinin bir dize olduğunu varsayalım; bu nedenle her karşılaştırma için durum numaralandırmalarını dizelere dönüştürmeniz gerekir. Bunları başlangıçta bir kez dönüştürebilir ve bununla bitirebilirsiniz.
XXXXX

Soruyu önemli ölçüde basitleştiren bir düzenleme yaptım, ancak bunu yaparken bu cevabı geçersiz kılıyor. Bunun için üzgünüm, ama genel olarak daha iyi olduğunu düşündüm.
Mark Amery

-1

Doğru anlıyorsam, Bina listesinde sakladığınız türü (char değeri) buildingStatus listesinde sakladığınız türe (enum) dönüştürmeniz gerekir.

(Bina listesindeki her bir durum için // karakter değeri //, durum buildingStatus listesinde // numaralandırma değeri // var mı?)

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; soruya yaptığım düzenleme, sorudan tüm referansları kaldırarak bu cevabı biraz geçersiz kılmış olsa da Building, bu zaten gerçekten kırılmıştı . foreach(Enum value in Enum.GetValues(typeof(buildingStatus)))saçmalıktır.
Mark Amery
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.