Глубокая фильтрация в сгруппированной коллекции сущностей

У меня есть следующая схема сущностей:

class Container
{
 Forest Forest;
 Tree Tree;
}
class Forest 
{
  int Id;
  string Name;
  List<Trees> Trees;
}

class Tree 
{
 int Id;
 string Name;
 Forest Forest;
 List<Leaf> Leafs;
}

class Leaf 
{
 int Id;
 string Name;
 Tree Tree;
}

У меня есть коллекция Forest с включенным Trees and Leafs чтением из базы данных.

Как я могу сделать следующее:

Отфильтруйте коллекцию Forests на основе следующего правила: Возьмите записи в лесу, у которых есть [Name] содержащие некоторые "filter value" Или те, у кого Trees[Name] содержит "filter value" Или тех, кто Leaf[Name] содержит "filter value".

Мне нужно вернуть иерархию леса, а не плоский вид леса

Я попытался сгладить структуру для фильтрации записей, таких как таблица в базе данных из представления INNER JOIN.

IEnumerable<Container> containers;
var groupped = forests.Select(f => new {f.Forest, f.Tree})
  .GroupBy(f => f.Forest)
  .ToList().Select(fs => new {Forest = fs.Key, Leafes = fs.SelectMany(g => g.Tree.Leafes) }).ToDictionary(fx => fx.Forest, fx => fx.Leafes);

var flat = new List<Tuple<Forest, Tree, Leaf>>;
foreach (var i in groupped)
{
 foreach (var l in i.Value) 
 {
  flat.Add((i.Key, l.Tree, l));
 }
}
flat.Where(d => d.Item1.Name.Contains("") 
  || d.Item2.Name.Contains("")
  || d.Item3.Name.Contains(""));       

Но на самом деле здесь я не могу объединить их обратно в иерархию Forest -> Tree -> Leaf

Итак, вместо табличной структуры List<Tuple<Forest,Tree,Leaf>> я хочу иметь обычную коллекцию List<Forest> с отфильтрованными Trees и Leafs.

вы хотите отфильтровать его на уровне базы данных или на уровне приложения?

Matt.G 20.06.2019 15:53

Почему в вашем классе Container есть участник Forest и участник Tree? Каково значение члена Tree? Вы говорите «Отфильтровать коллекцию лесов», но в вашем коде нет коллекции Forest. И что означает «с отфильтрованными деревьями и листьями»?

NetMage 20.06.2019 20:32
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
445
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете довольно легко создать набор фильтров Container из своего списка Containers, просто реализуйте желаемый фильтр точно так, как вы его написали. (Это не (обязательно) самый эффективный способ поиска, но, вероятно, довольно близкий.)

var ans = src.Where(c => c.Forest.Name.Contains(fv) || // Forest name contains filter value
                         c.Forest.Trees.Any(t => t.Name.Contains(fv) || // a Tree name contains filter value
                                                 t.Leafs.Any(l => l.Name.Contains(fv))) // a Leaf name contains filter value
                    );

Если в вашей иерархии мало деревьев и много листьев, вы можете сначала изменить поиск на поиск по деревьям, а затем выполнить отдельный поиск по дереву->лист, даже если это делает два прохода по деревьям.

var ans2 = src.Where(c => c.Forest.Name.Contains(fv) || // Forest name contains filter value
                          c.Forest.Trees.Any(t => t.Name.Contains(fv)) || // a Tree name contains filter value
                          c.Forest.Trees.Any(t => t.Leafs.Any(l => l.Name.Contains(fv))) // a Leaf name contains filter value
                    );

Другие вопросы по теме