Фильтрация списка с помощью LINQ
У меня есть список объектов проекта:
IEnumerable<Project> projects
a Проект как свойство, называемое Теги. это int []
У меня есть переменная, называемая отфильтрованной теги, которая также является int [].
Итак, скажем, переменная фильтрованных тегов выглядит так:
int[] filteredTags = new int[]{1, 3};
Я хочу отфильтровать свой список (projects), чтобы возвращать только проекты, в которых есть ВСЕ теги, перечисленные в фильтре (в этом случае, по крайней мере, тег 1 И тег 3 в тегах ).
Я пытался использовать Где() и Содержит(), но это работает, только если я сравниваю одно значение. Как бы это сделать, чтобы сравнить список с другим списком, где мне нужно совпадение по всем элементам в отфильтрованном списке?
Ответы
Ответ 1
EDIT: еще лучше, сделайте так:
var filteredProjects =
projects.Where(p => filteredTags.All(tag => p.Tags.Contains(tag)));
EDIT2: Честно говоря, я не знаю, какой из них лучше, поэтому, если производительность не является критичной, выберите ту, которую вы считаете более читаемой. Если это так, вам придется каким-то образом оценить его.
Вероятно, Intersect
- это путь:
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;
}
Хотя сначала это кажется немного уродливым. Вы можете сначала применить Distinct
к filteredTags
, если вы не уверены, все ли они уникальны в списке, иначе сравнение отсчетов не будет работать должным образом.
Ответ 2
var result = projects.Where(p => filtedTags.All(t => p.Tags.Contains(t)));
Ответ 3
var res = projects.Where(p => filteredTags.Except(p.Tags).Count() == 0);
Ответ 4
var filtered = projects;
foreach (var tag in filteredTags) {
filtered = filtered.Where(p => p.Tags.Contains(tag))
}
Хорошая вещь с этим подходом заключается в том, что вы можете улучшить результаты поиска постепенно.
Ответ 5
На основе http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b,
EqualAll - это подход, который наилучшим образом отвечает вашим потребностям.
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);
}
Ответ 6
Попробуйте следующее:
var filteredProjects =
projects.Where(p => filteredTags.All(tag => p.Tags.Contains(tag)));