Comment faire une recherche Hiérarchique des Données avec Linq
J'ai besoin de recherche dans un arbre pour les données qui pourrait être n'importe où dans l'arborescence. Comment cela peut-il être fait avec linq?
class Program
{
static void Main(string[] args) {
var familyRoot = new Family() {Name = "FamilyRoot"};
var familyB = new Family() {Name = "FamilyB"};
familyRoot.Children.Add(familyB);
var familyC = new Family() {Name = "FamilyC"};
familyB.Children.Add(familyC);
var familyD = new Family() {Name = "FamilyD"};
familyC.Children.Add(familyD);
//There can be from 1 to n levels of families.
//Search all children, grandchildren, great grandchildren etc, for "FamilyD" and return the object.
}
}
public class Family {
public string Name { get; set; }
List<Family> _children = new List<Family>();
public List<Family> Children {
get { return _children; }
}
}
OriginalL'auteur Greg Gum | 2013-08-10
Vous devez vous connecter pour publier un commentaire.
C'est une extension de
Il'sNotALie.
réponse de s.Test de l'échantillon d'utilisation:
Retourne
familyD
objet.Vous pouvez le faire fonctionner sur
IEnumerable<T>
source:Tout ce que vous avez sur votre blog est juste, la mise en œuvre de l'aplatir sur IEnumerable<T> ici ne l'est pas. Il permettra de créer des doublons...
Je ne suis pas de voir que, bien que chaque nœud de l'objet retourné sera toujours avoir son complément d'enfants.
Je retire ce que, le dernier exemple permet de dupliquer des racines; l'édition.
OriginalL'auteur MarcinJuraszek
Une autre solution sans récursivité...
OriginalL'auteur EZI
Simple:
Pourriez-vous me montrer les code? J'ai le sentiment que le haut niveau de l'objet n'est pas du même type que pour les enfants...
Je suis juste essayer de l'utiliser dans l'exemple d'application. Je viens d'ajouter votre réponse à la ci-dessus. Si vous collez-le dans VS, vous verrez le compilateur message.
OriginalL'auteur It'sNotALie.
J'aime Kenneth Bo Christensen de la réponse à l'aide de la pile, il fonctionne très bien, il est facile à lire et c'est rapide (et ne pas utiliser la récursivité).
La seule mauvaise chose, c'est qu'il inverse l'ordre des éléments enfants (parce que la pile FIFO). Si l'ordre de tri n'est pas question pour vous, alors il est ok.
Si il n', le tri peut être réalisé facilement à l'aide du sélecteur(en cours).Reverse() dans la boucle foreach (le reste du code est le même que dans Kenneth original post)...
OriginalL'auteur sth_Weird
Bien, je suppose que le moyen est d'aller avec la technique de travail avec les structures hiérarchiques:
Vous avez besoin de la récursivité partie
OriginalL'auteur Saeed Neamati
Ainsi, l'option la plus simple est d'écrire une fonction qui parcourt votre hiérarchie et produit une seule séquence. Ensuite, cela se passe au début de votre LINQ opérations, par exemple
D'appeler simplement: familyRoot.Aplatir().Où(n => n.Nom == "Bob");
Une légère alternative serait de vous donner un moyen rapide pour ignorer une branche entière:
Ensuite, vous pouvez faire des choses comme: la famille.Aplatir(n => n.Les enfants.Count > 2).Où(...)
OriginalL'auteur DamienG
J'ai essayé deux de ces codes et fait un peu le code plus clair:
Flatten2() semble être un peu plus rapide, mais son une proche exécuter.
OriginalL'auteur Kenneth Bo Christensen
Quelques variantes sur les réponses de'sNotALie., MarcinJuraszek et DamienG.
Tout d'abord, les deux anciens de donner un contre-intuitif de la commande. Pour obtenir un joli arbre de la traversée de la commande pour les résultats, il suffit d'inverser la concaténation (mettre la "source" de la première).
Deuxième, si vous travaillez avec une chère comme EF, et que vous souhaitez limiter l'ensemble d'une branche, Damien suggestion que vous injectez le prédicat est bon et qui peut encore être fait avec Linq.
Enfin, pour un chers à la source, il peut aussi être bon pour pré-sélectionner les champs d'intérêt de chaque nœud avec l'injection d'une sélection.
Mettre tous ces ensemble:
OriginalL'auteur Marc L.