リストにリストが含まれている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 2015年

@stom:それを支援するのに十分な情報がありません- より多くのコンテキストで新しい質問をする必要あります。
Jon Skeet

@JonSkeetこれらの種類のクエリには、常にContainsメソッドを使用します。私はあなたの答えを見て興味があり、内部の実装を確認しましたが、IntersectがSetを使用していることがわかりました。これら2つの方法のパフォーマンスの違いを教えてください。
rebornx 2017

6
@Rebornx:Contains繰り返し使用すると、時間の経過とともにO(x * y)操作として終了しますが、空間ではO(1)となります。ここで、xは最初のコレクションのサイズ、yは2番目のコレクションのサイズです。使用時IntersectはO(x + y)、空間内はO(y)-2番目のコレクションからハッシュセットを作成します。これにより、最初のコレクションのアイテムが含まれているかどうかをすばやく確認できます。詳細については、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スタンリー

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.