过滤掉RoseTree中的元素

时间:2017-08-16 20:10:23

标签: haskell

我正在尝试编写一个函数filterTree,它将使用给定条件过滤掉RoseTree中的元素:

data RoseTree a = RoseTree a [RoseTree a]
                   deriving (Show, Functor)

extractChild :: RoseTree a -> RoseTree a
extractChild (RoseTree _ (x:[])) = x
extractChild rTree = rTree

filterTree :: ( a -> Bool ) -> RoseTree a -> RoseTree a
filterTree condition rTree@(RoseTree a list) = 
    if (condition $ a) 
      then (extractChild rTree)  
      else (RoseTree a (filterTreeList condition list)) 

filterTreeList :: (a -> Bool) -> [RoseTree a] -> [RoseTree a]
filterTreeList condition [] = []
filterTreeList condition (x:xs) = [filterTree condition x] ++ (filterTreeList condition xs)

但它并不像预期的那样有效。由于某种原因,它不会过滤掉满足条件的嵌套元素。例如,如果我运行

filterTree (==2) (RoseTree 1 [ RoseTree 2 [ RoseTree 3 [] ]])

然后它运行良好返回RoseTree 1 [RoseTree 3 []]。但是如果我用另一个满足条件的嵌套元素运行它

filterTree (==2) (RoseTree 1 [ RoseTree 2 [ RoseTree 3 [RoseTree 2 [RoseTree 1[]]] ]])

然后它返回错误的结果,列表中有第二个匹配元素:RoseTree 1 [RoseTree 3 [RoseTree 2 [RoseTree 1 []]]]

为什么会发生这种情况的任何想法?

1 个答案:

答案 0 :(得分:2)

以下内容适用于您提供的示例。

请注意,如果节点与过滤条件匹配且没有一个子节点,它将循环。

filterTree :: ( a -> Bool ) -> RoseTree a -> RoseTree a
filterTree condition rTree@(RoseTree a list) = 
    if (condition $ a) 
      then filterTree condition (extractChild rTree)
      else (RoseTree a (filterTreeList condition list))