LINQ:「含む」とLambdaクエリ


168

List<BuildingStatus>呼ばれていbuildingStatusます。文字コード(によって返されるGetCharCode())がある変数に等しいステータスが含まれているかどうかを確認したいのですが、v.Status

以下の(非コンパイル)コードの行に沿ってこれを行う方法はありますか?

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

回答:


320

Any()代わりに使用Contains()

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

13
いいね。私はなぜ地球上でLinqがContains()メソッドを提供していないのか疑問に思っていますAny()。+1
Nolonar

38

Linq拡張メソッドAnyはあなたのために働くことができます...

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

4

これは、あなたがContains望むものを達成するためにどのように使用できるかです:

buildingStatus.Select(item => item.GetCharValue()).Contains(v.Status) これはブール値を返します。


3

あなたが何を探しているのか正確にはわかりませんが、このプログラム:

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

期待される出力を生成します:

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

このプログラムは、列挙型の文字列表現を比較し、同じ出力を生成します。

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

あるIEnumerableを別のIEnumerableに変換するためにこの拡張メソッドを作成しましたが、それがどれほど効率的かはわかりません。裏でリストを作成するだけかもしれません。

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

次に、where句を次のように変更できます。

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

で最初にを作成するのList<string>をスキップしConvertAll ()ます。


うまくいったラリーのおかげで、ここに私はあなたのコードを参照して何をしたかです...しかし、もし私が新しいリストを作成する必要がなかったら、できればそれは素晴らしいでしょう???? // ILISTを使用してToListを使用し、GetCharValueを実行した//これにより、charのvarを含む「NEW」リストが作成されたstatusStringList = building.ToList()。var test = from vry qry where statusStringList.Contains(v.Status)select v; 新しいリストを作成したり、Contains内でラムダを使用したりしなくてもいいのに、とはいえ、それは不可能と思われますか?
マークスミス

statusプロパティは文字列だと思います。したがって、比較のたびにステータス列挙型を文字列に変換する必要があります。あなたは最初に一度それらを変換して、それで終わらせたほうがいいでしょう。
XXXXX、

質問を大幅に簡略化する編集を行いましたが、そうすることで、この回答はある程度無効になります。それについて申し訳ありませんが、私はそれが全体的にもっと良いもののためであると考えました
Mark Amery

-1

私が正しく理解している場合は、Buildingリストに格納するタイプ(char値)をbuildingStatusリストに格納するタイプ(enum)に変換する必要があります。

(Buildingリストの各ステータス//文字値//、ステータスはbuildingStatusリストに存在しますか//列挙値//)

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; 質問への私の編集は質問からへのすべての参照を削除することによってこの回答をわずかに無効にBuildingしましたが、これはすでに本当に壊れていましたforeach(Enum value in Enum.GetValues(typeof(buildingStatus)))ナンセンスです。
Mark Amery
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.