LINQ : "포함"및 Lambda 쿼리


168

나는 한 List<BuildingStatus>이라고 buildingStatus. char 코드 (로 반환 GetCharCode())가 일부 변수와 같은 상태를 포함하고 있는지 확인하고 싶습니다 v.Status.

아래의 (비 컴파일) 코드 라인을 따라이 작업을 수행하는 방법이 있습니까?

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

답변:


320

Any()대신에 사용하십시오 Contains():

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

13
좋은. Earth Linq가 왜 Contains()방법을 제공하지 않는지 계속 궁금해 하며 Any()대신 그 방법이 필요하다는 것을 깨달았습니다 . +1
Nolonar

38

Linq 확장 방법 모든 것이 당신을 위해 일할 수 있습니다 ...

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"목록을 생성합니다. var statusStringList = building.ToList (). ConvertAll <char> (st => st.GetCharValue ()); var test = q의 v에서 from statusStringList.Contains (v.Status) select v; 내가 말하는 것처럼 모든 작품은 새 목록을 작성하지 않아도되거나 Contains 안에 람다를 사용할 필요는 없지만 불가능한 것처럼 보입니까?
mark smith

상태 속성이 문자열이라고 가정합니다. 따라서 각 비교를 위해 상태 열거 형을 문자열로 변환해야합니다. 처음에 한 번 변환하여 완료 할 수도 있습니다.
XXXXX

질문을 크게 단순화하는 편집 작업을 수행했지만 그렇게하면이 답변이 무효화됩니다. 그것에 대해 미안하지만 전반적으로 더 좋은 것으로 생각했습니다.
Mark Amery

-1

올바르게 이해하면 건물 목록에 저장하는 유형 (문자 값)을 buildingStatus 목록에 저장하는 유형 (열)으로 변환해야합니다.

(Building list // character value //의 각 상태에 대해 buildingStatus list // 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; 질문에 대한 나의 편집은 질문 Building에서 모든 참조를 제거 하여이 답변을 약간 무효화 했지만 실제로실제로 고장 났습니다 . foreach(Enum value in Enum.GetValues(typeof(buildingStatus)))말도 안됩니다.
Mark Amery
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.