2011-02-23 28 views
27

tengo una lista de los objetos del proyecto:filtrar una lista utilizando LINQ

IEnumerable<Project> projects 

un Proyecto clase como una propiedad llamada Etiquetas. este es un int []

tengo una variable llamada filteredTags que es también un int [].

lo que permite decir que mi variable de etiquetas filtrada se ve así:

int[] filteredTags = new int[]{1, 3}; 

quiero filtrar mi lista (proyectos) a devolver sólo los proyectos que tienen todas las etiquetas que figuran en el filtro (en este case al menos tag 1 AND tag 3 en la propiedad Tags).

yo estaba tratando de utilizar Dónde() y Contiene(), pero que sólo parece funcionar si yo estoy comparando contra un solo valor. ¿Cómo haría esto para comparar una lista con otra lista donde necesito una coincidencia en todos los artículos en la lista filtrada?

Respuesta

37

EDIT: mejor aún, hacerlo así:

var filteredProjects = 
    projects.Where(p => filteredTags.All(tag => p.Tags.Contains(tag))); 

Edit2: Honestamente, no sé cuál es mejor, por lo que si el rendimiento no es crítico, elegir el que usted piensa es más legible Si es así, tendrás que compararlo de alguna manera.


Probablemente Intersect es el camino a seguir:

void Main() 
{ 
    var projects = new List<Project>(); 
    projects.Add(new Project { Name = "Project1", Tags = new int[] { 2, 5, 3, 1 } }); 
    projects.Add(new Project { Name = "Project2", Tags = new int[] { 1, 4, 7 } }); 
    projects.Add(new Project { Name = "Project3", Tags = new int[] { 1, 7, 12, 3 } }); 

    var filteredTags = new int []{ 1, 3 }; 
    var filteredProjects = projects.Where(p => p.Tags.Intersect(filteredTags).Count() == filteredTags.Length); 
} 


class Project { 
    public string Name; 
    public int[] Tags; 
} 

A pesar de que parece un poco feo en un principio. Primero puede aplicar Distinct a filteredTags si no está seguro de si son únicos en la lista, de lo contrario, la comparación de recuentos no funcionará como se esperaba.

+0

Creo que su 'Intersección 'la forma es más clara que su método 'mejor aún' ​​ – AakashM

+0

@AakashM: realmente no lo sé y estoy tratando de decidirlo ahora mismo. No me gusta' Count() 'porque tiene que evaluar las etiquetas 'IEnumerable', pero estoy desconcertado – Dyppl

2
var result = projects.Where(p => filtedTags.All(t => p.Tags.Contains(t))); 
+0

¿Por qué? No permitirá el proyecto con las etiquetas "1, 2, 3" o ¿me falta algo? – Dyppl

+0

No estoy seguro de que TODO esté correcto ya que debe funcionar si tiene ATLEAST 1 y 3 pero puede tener más que eso. . . ¿All() no va a validar cada elemento en la lista contra 1 y 3? – leora

+0

podemos modificar ligeramente el código anterior para lograr el resultado deseado. var result = projects.Where (p => filtedTags.All (t => p.Tags.Contains (t)) –

1
var filtered = projects; 
foreach (var tag in filteredTags) { 
    filtered = filtered.Where(p => p.Tags.Contains(tag)) 
} 

Lo bueno de este enfoque es que puede refinar los resultados de búsqueda de forma incremental.

2
var res = projects.Where(p => filteredTags.Except(p.Tags).Count() == 0); 
1

Basado en http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b,

EqualAll es el enfoque que mejor se adapte a sus necesidades.

public void Linq96() 
{ 
    var wordsA = new string[] { "cherry", "apple", "blueberry" }; 
    var wordsB = new string[] { "cherry", "apple", "blueberry" }; 

    bool match = wordsA.SequenceEqual(wordsB); 

    Console.WriteLine("The sequences match: {0}", match); 
} 
0

Prueba esto:

var filteredProjects = 
projects.Where(p => filteredTags.All(tag => p.Tags.Contains(tag))); 
+0

Bienvenido a SO, por favor formatee su código y escriba una pequeña descripción. – cSteusloff

Cuestiones relacionadas