objectmodel library generic collection clase c# linq collections tags ienumerable

c# - library - system collection



filtrando una lista usando LINQ (6)

tengo una lista de objetos del proyecto:

IEnumerable<Project> projects

una clase Project como propiedad llamada Etiquetas . esto es un int []

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

Entonces digamos que mi variable de etiquetas filtradas se ve así:

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

Deseo filtrar mi lista ( proyectos ) para que solo devuelva proyectos que tengan TODAS las etiquetas enumeradas en el filtro (en este caso, como mínimo, etiquete 1 AND tag 3 en la propiedad Tags ).

Intenté usar Where () y Contains (), pero eso solo parece funcionar si estoy comparando con 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?


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

EqualAll es el enfoque que mejor se adapta a tus 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); }


EDITAR: mejor aún, hazlo así:

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

EDIT2: Honestamente, no sé cuál es mejor, así que si el rendimiento no es crítico, elija el que crea 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; }

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


Prueba esto:

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


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.


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


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