linq donde la lista contiene cualquiera en la lista


117

Usando linq, ¿cómo puedo recuperar una lista de elementos donde su lista de atributos coincide con otra lista?

Tome este simple ejemplo y pseudo código:

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

Respuestas:


202

Suena como que quieres:

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

Estaba tratando de usar esta consulta para el cuadro de búsqueda, busca cualquier carácter en la columna Person_Name, recibí este error: 'DbIntersectExpression requiere argumentos con una colección compatible ResultTypes', así que lo intenté .StartWith, .EndsWith, .Containsdesde aquí , funciona, pero ¿qué se puede hacer para usar su consulta?
shaijut

@stom: No tenemos suficiente información para ayudarte con eso; deberías hacer una nueva pregunta con mucho más contexto.
Jon Skeet

@JonSkeet Siempre uso el método Contains para este tipo de consultas. Tenía curiosidad al ver su respuesta y verifiqué la implementación interna y descubrí que Intersect usa Set. ¿Puede decirme la diferencia de rendimiento entre esos dos métodos?
rebornx

6
@Rebornx: El uso Containsrepetido termina como una operación O (x * y) en el tiempo, pero O (1) en el espacio, donde x es el tamaño de la primera colección e y es el tamaño de la segunda. El uso de Intersectes O (x + y) en el tiempo pero O (y) en el espacio: construye un conjunto de hash de la segunda colección, lo que agiliza la verificación de la inclusión de cualquier elemento de la primera colección. Consulte codeblog.jonskeet.uk/2010/12/30/… para más detalles
Jon Skeet

1
@SteveBoniface: No lo esperaba, no. Esperaría que este último sea un poco más rápido, ya que hay menos indirectas.
Jon Skeet

60

Puede utilizar una Containsconsulta para esto:

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

5

Si usa en HashSetlugar de Listfor listofGenrespuede hacer:

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

3

¿Supongo que esto también es posible así?

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

¿Es "TakeWhile" peor que "Where" en términos de rendimiento o claridad?


TakeWhilees una función diferente: dejará de iterar cuando no encuentre una coincidencia.
D Stanley

1

O así

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();
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.