linq, listenin listedeki herhangi birini içerdiği yer


117

Linq kullanarak, öznitelik listesinin başka bir listeyle eşleştiği bir öğe listesini nasıl alabilirim?

Bu basit örneği ve sözde kodu ele alalım:

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

Yanıtlar:


202

İstediğin gibi geliyor:

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

i arama kutusu için bu sorguyu kullanmak çalışıyordu, PERSON_NAME sütununda herhangi bir karakter arar ben bu hata var: denedim bu yüzden 'DbIntersectExpression uyumlu toplama ResultTypes ile argümanlar gerektirir' .StartWith, .EndsWith, .Containsdan buraya çalıştığını, ama ne Sorgunuzla kullanmak yapılabilir
shaijut

@stom: Bu konuda size yardımcı olacak neredeyse yeterli bilgiye sahip değiliz - çok daha fazla bağlam içeren yeni bir soru sormalısınız .
Jon Skeet

@JonSkeet Bu tür sorgular için her zaman Contains yöntemini kullanıyorum. Cevabınızı görerek merak ettim ve dahili uygulamayı kontrol ettim ve Intersect'in Set kullandığını gördüm. Bu iki yöntem arasındaki performans farkını bana söyleyebilir misiniz?
rebornx

6
@Rebornx: ContainsTekrar tekrar kullanılması , zamanda bir O (x * y) işlemi olarak sona erer, ancak uzayda O (1), burada x ilk koleksiyonun boyutu ve y, ikincinin boyutudur. Kullanılması Intersectsürede O (x + y) ancak O (y) uzayda - bu hızlı ilk koleksiyonundan herhangi bir öğe için eklenmesi için kontrol kolaylaştırır ikinci koleksiyonundan bir HashSet oluşturur. Ayrıntılar için codeblog.jonskeet.uk/2010/12/30/… bakın
Jon Skeet

1
@SteveBoniface: Öyle olmasını beklemiyordum, hayır. Daha az dolaylı olduğu için ikincisinin biraz daha hızlı olmasını beklerdim.
Jon Skeet

60

Bunun için bir Containssorgu kullanabilirsiniz :

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

5

Eğer kullanırsanız HashSetyerine Listiçin listofGenresyapabileceğiniz:

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

3

Sanırım bu da böyle mümkün?

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

"TakeWhile", performans veya netlik açısından "Nerede" den daha mı kötü?


TakeWhilefarklı bir işlevdir - eşleşme bulamadığında yinelemeyi durdurur.
D Stanley

1

Veya bunun gibi

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