목록에 목록에있는 항목이있는 linq


117

linq를 사용하여 속성 목록이 다른 목록과 일치하는 항목 목록을 검색하려면 어떻게해야합니까?

이 간단한 예제와 의사 코드를 사용하십시오.

List<Genres> listofGenres = new List<Genre>() { "action", "comedy" });   
var movies = _db.Movies.Where(p => p.Genres.Any() in listofGenres);

답변:


202

원하는 것 같습니다.

var movies = _db.Movies.Where(p => p.Genres.Intersect(listOfGenres).Any());

내가 검색 상자에이 쿼리를 사용하려고했다가 PERSON_NAME 열에서 모든 문자를 검색,이 오류가 발생했습니다 : 내가 노력 있도록 'DbIntersectExpression 호환 수집 ResultTypes에 인수가 필요합니다' .StartWith, .EndsWith, .Contains에서 여기 작동,하지만 당신의 쿼리를 사용하여 수행 할 수 있습니다
shaijut

@stom : 우리는 도움을 거의 충분한 정보를 가지고 있지 않습니다 - 당신이 가진 새로운 질문을해야 훨씬 더 상황.
Jon Skeet

@JonSkeet 저는 이러한 종류의 쿼리에 항상 Contains 메서드를 사용합니다. 귀하의 답변을보고 궁금한 점이 있었고 내부 구현을 확인한 결과 Intersect가 Set을 사용한다는 것을 알았습니다. 두 방법의 성능 차이를 말씀해 주시겠습니까?
rebornx

6
@Rebornx : Contains반복적으로 사용하면 시간상 O (x * y) 연산으로 끝나지만 공간에서는 O (1)으로 끝납니다. 여기서 x는 첫 번째 컬렉션의 크기이고 y는 두 번째 컬렉션의 크기입니다. Using Intersectis O (x + y) in time but O (y) in space-두 번째 컬렉션에서 해시 세트를 구성하여 첫 번째 컬렉션의 항목 포함 여부를 빠르게 확인할 수 있습니다. 참조 codeblog.jonskeet.uk/2010/12/30/... 자세한 내용은
존 소총을

1
@SteveBoniface : 나는 그렇게 기대하지 않을 것입니다. 간접적이 적기 때문에 후자는 매우 약간 더 빠를 것으로 예상합니다.
Jon Skeet

60

이를 위해 Contains쿼리를 사용할 수 있습니다 .

var movies = _db.Movies.Where(p => p.Genres.Any(x => listOfGenres.Contains(x));

5

for HashSet대신 사용 하면 다음을 수행 할 수 있습니다.ListlistofGenres

var genres = new HashSet<Genre>() { "action", "comedy" };   
var movies = _db.Movies.Where(p => genres.Overlaps(p.Genres));

3

이것도 가능할까요?

var movies = _db.Movies.TakeWhile(p => p.Genres.Any(x => listOfGenres.Contains(x));

성능이나 명확성면에서 "TakeWhile"이 "Where"보다 나쁩니 까?


TakeWhile은 다른 기능입니다. 일치하는 항목을 찾지 못하면 반복을 중지합니다.
D Stanley

1

아니면 이렇게

class Movie
{
  public string FilmName { get; set; }
  public string Genre { get; set; }
}

...

var listofGenres = new List<string> { "action", "comedy" };

var Movies = new List<Movie> {new Movie {Genre="action", FilmName="Film1"},
                new Movie {Genre="comedy", FilmName="Film2"},
                new Movie {Genre="comedy", FilmName="Film3"},
                new Movie {Genre="tragedy", FilmName="Film4"}};

var movies = Movies.Join(listofGenres, x => x.Genre, y => y, (x, y) => x).ToList();
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.