2017-05-10 1 views
1

J'essaie de comprendre la structure de l'arbre scalaz et j'ai de la difficulté!Traverser Scalaz Tree

D'abord, je l'ai défini un arbre:

val tree: Tree[Int] = 
     1.node(
     2.leaf, 
     3.node(
      4.leaf, 
      5.leaf)) 

Jusqu'à présent, en utilisant TreeLoc Je travaille sur la façon de trouver l'élément premier qui correspond à un certain prédicat. Par exemple. pour trouver le premier nœud où la valeur est 3:

tree.loc.find(x => x.getLabel == 3) 

Mon prochain défi est d'essayer de trouver tous les nœuds qui correspondent à un certain prédicat. Par exemple je voudrais trouver tous les noeuds de feuille (qui devrait être assez facile using TreeLoc et isLeaf). Malheureusement, je ne peux pas pour la vie de moi travailler sur la marche de l'arbre pour le faire.

Editer: Désolé, je ne pense pas avoir été assez clair dans ma question originale. Pour être clair, je veux marcher sur l'arbre de telle sorte que j'ai des informations sur le nœud à ma disposition. Aplatir, foldRight etc juste permettez-moi de fonctionner sur [Int] alors que je veux être capable de fonctionner sur Tree [Int] (ou TreeLoc [Int]).

+0

Comment voulez-vous les résultats? L'approche la plus directe (si vous n'avez pas d'exigences plus spécifiques) consisterait à utiliser 'flatten' sur l'arbre, puis à filtrer le' Stream' résultant. –

+0

Quel type de traversée d'arbres souhaitez-vous réaliser? Cela a un impact sur l'ordre de votre sortie (si vous y tenez vraiment). –

+0

@TravisBrown: mon exigence (désolé, j'aurais dû être plus clair sur ce point) est que je veux marcher sur les nœuds et non sur les valeurs. Dans ce cas, aplatir me donnerait un flux d'Ints, donc vous n'auriez (par exemple) aucun moyen de savoir si l'int provenait d'un nœud ou d'une feuille. – d80tb7

Répondre

1

Avoir un regard sur la façon dont find est mis en œuvre en scalaz, ma suggestion est de mettre en œuvre quelque chose comme:

implicit class FilterTreeLoc[A](treeLoc: TreeLoc[A]){ 
    def filter(p: TreeLoc[A] => Boolean): Stream[TreeLoc[A]] = 
    Cobind[TreeLoc].cojoin(treeLoc).tree.flatten.filter(p) 
} 

Il se comporte comme le find mais il vous donne de nouveau à la place une Stream[TreeLoc[A]] au lieu d'un Option[TreeLoc[A]]. Vous pouvez utiliser ceci comme tree.loc.filter(_.isLeaf) et tree.loc.filter(_.getLabel == 3).

Remarque: l'utilisation d'une classe implicite peut évidemment être évitée si vous préférez que cela soit déclaré comme méthode à la place.