For loop Elm-tree-将分支添加到另一棵树-递归forloop
我想把榆树的树枝从一棵树移到另一棵树 例如: 树1:For loop Elm-tree-将分支添加到另一棵树-递归forloop,for-loop,recursion,functional-programming,tree,elm,For Loop,Recursion,Functional Programming,Tree,Elm,我想把榆树的树枝从一棵树移到另一棵树 例如: 树1: A-1 - A-1-1 - - A-1-1-1 - - A-1-1-2 - - - A-1-1-2-1 - - - A-1-1-2-2 树2 B-1 - B-1-1 - - B-1-1-1 - - B-1-1-2 - - - B-1-1-2-1 - - - B-1-1-2-2 我想把A-1-1移到B-1-1-2-1下面,这样应该会 B-1 - B-1-1 - - B-1-1-1 - - B-1-1-2 - - - B-1-1-2-1 -
A-1
- A-1-1
- - A-1-1-1
- - A-1-1-2
- - - A-1-1-2-1
- - - A-1-1-2-2
树2
B-1
- B-1-1
- - B-1-1-1
- - B-1-1-2
- - - B-1-1-2-1
- - - B-1-1-2-2
我想把A-1-1移到B-1-1-2-1下面,这样应该会
B-1
- B-1-1
- - B-1-1-1
- - B-1-1-2
- - - B-1-1-2-1
- - - - A-1-1
- - - - - A-1-1-1
- - - - - A-1-1-2
- - - - - - A-1-1-2-1
- - - - - - A-1-1-2-2
- - - B-1-1-2-2
我不熟悉函数式编程。我可以想象如何在Python中使用递归forloop来实现这一点,但我仍然坚持使用Elm
我可以轻松地移动一个节点,但我不知道如何递归添加子节点:
module Main exposing (..)
import Canopy exposing (Node, append, children, leaf, mapChildren, node, value)
import Html exposing (Html, b, div, h1, h2, li, text, ul)
import List exposing (map)
tree1 : Node String
tree1 =
node "A-1"
[ node "A-1-1"
[ leaf "A-1-1-1"
, node "A-1-1-2"
[ leaf "A-1-1-2-1"
, leaf "A-1-1-2-2"
]
]
]
tree2 : Node String
tree2 =
node "B-1"
[ node "B-1-1"
[ leaf "B-1-1-1"
, node "B-1-1-2"
[ leaf "B-1-1-2-1"
, leaf "B-1-1-2-2"
]
]
]
tree3 : Node String
tree3 =
let
nodeToMove =
"A-1-1"
newParentNode =
"B-1-1-2-1"
-- append the node only but not its descendants
treeWithNewNode =
append newParentNode nodeToMove tree2
-- type mismatch
-- treeWithNewNodeAndNewNodeChildren =
-- nodeToMove |> mapChildren (\child -> append
-- does not do what I was hopping for
-- newTree =
-- mapChildrenAt
-- nodeToMove
-- (\child -> append newParentNode (value child) treeWithNewNode)
-- tree2
newParentNode child tree2)
in
treeWithNewNode
main =
div []
[ h1 [] [ text "Adding a branch to another tree" ]
, h2 [] [ text "Tree 1" ]
, viewNode tree1
, h2 [] [ text "Tree 2" ]
, viewNode tree2
, h2 [] [ text "Move A-1-1 under B-1-1-2-1" ]
, viewNode tree3
]
viewNode : Node String -> Html msg
viewNode node =
let
subNodes =
children node
in
li []
[ b [] [ text (value node) ]
, ul [] (List.map viewNode subNodes)
]
我的审判在这里:
我在这里使用的是Canopy,但如果推荐的话,我可以使用另一个库。在您的代码中,在我看来,您从未从
tree1
中提取A-1-1
的子项,所以让我们从这一点开始:
subtreeToMove =
Maybe.withDefault (leaf <| "Failed to find node " ++ nodeToMove) <| get nodeToMove tree1
之所以提到这一点,是因为您将所需的结果描述为在树之间移动节点:所有数据在Elm中都是不可变的–因此,在移动之后,
tree1
和tree2
仍然是相同的。因此,将tree1
中的子树复制到tree2
我的解决方案的副本中,而不使用replaceChildrenAt
,以保留现有子级
module Main exposing (main)
import Canopy exposing (Node, append, children, get, leaf, node, value)
import Html exposing (Html, b, div, h1, h2, li, text, ul)
-- add a node (and its children) under a branch in another tree
tree1 : Node String
tree1 =
node "A-1"
[ node "A-1-1"
[ leaf "A-1-1-1"
, node "A-1-1-2"
[ leaf "A-1-1-2-1"
, leaf "A-1-1-2-2"
]
]
]
tree2 : Node String
tree2 =
node "B-1"
[ node "B-1-1"
[ leaf "B-1-1-1"
, node "B-1-1-2"
[ node "B-1-1-2-1"
[ leaf "don't remove me"
]
, leaf "B-1-1-2-2"
]
]
]
tree3 : Node String
tree3 =
let
nodeToMove =
Maybe.withDefault (leaf <| "Failed to find node " ++ "A-1-1") <| get "A-1-1" tree1
newParentNodeValue =
"B-1-1-2-1"
treeWithNewNode =
tree2 |> addNodeAt nodeToMove newParentNodeValue
in
treeWithNewNode
-- treeWithNewNode
main =
div []
[ h1 [] [ text "Adding a branch to another tree" ]
, h2 [] [ text "Tree 1" ]
, viewNode tree1
, h2 [] [ text "Tree 2" ]
, viewNode tree2
, h2 [] [ text "Move A-1-1 under B-1-1-2-1" ]
, viewNode tree3
]
viewNode : Node String -> Html msg
viewNode node =
let
subNodes =
children node
in
li []
[ b [] [ text (value node) ]
, ul [] (List.map viewNode subNodes)
]
addNodeAt : Node String -> String -> Node String -> Node String
addNodeAt node firstParentNodeValue toTree =
--Canopy.toList ->
-- [("A-1-1",Nothing),("A-1-1-1",Just "A-1-1"),("A-1-1-2",Just "A-1-1"),...]
node
|> Canopy.toList
|> List.foldl
-- acc is the updated toTree
(\( nodeValue, parentValue ) acc ->
append
(Maybe.withDefault firstParentNodeValue parentValue)
nodeValue
acc
)
-- initial value
toTree
模块主显示(主)
导入(节点、附加、子节点、获取、叶、节点、值)
导入Html(Html、b、div、h1、h2、li、文本、ul)
--在另一棵树的分支下添加节点(及其子节点)
tree1:节点字符串
树1=
节点“A-1”
[节点“A-1-1”
[叶“A-1-1-1”
,节点“A-1-1-2”
[叶“A-1-1-2-1”
,叶“A-1-1-2-2”
]
]
]
tree2:节点字符串
树2=
节点“B-1”
[节点“B-1-1”
[叶“B-1-1-1”
,节点“B-1-1-2”
[节点“B-1-1-2-1”
[leaf“不要带走我”
]
,叶“B-1-1-2-2”
]
]
]
tree3:节点字符串
树3=
让
nodeToMove=
Maybe.withDefault(叶Html消息
视图节点=
让
子节点=
子节点
在里面
li[]
[b[]文本(值节点)]
,ul[](List.map视图节点子节点)
]
添加节点吃:节点字符串->字符串->节点字符串->节点字符串
AddNodeEat节点firstParentNodeValue到树=
--Canopy.toList->
--[(“A-1-1”,没什么),(“A-1-1-1”,只是“A-1-1”),(“A-1-1-2”,只是“A-1-1”),…]
节点
|>托利斯特酒店
|>List.foldl
--acc是更新的toTree
(\(nodeValue,parentValue)acc->
追加
(可能是默认的firstParentNodeValue parentValue)
节点值
行政协调会
)
--初始值
托特里
此处可见:
@o-o-balance的回答和这个:对我帮助很大。请在这里发布完整的代码,包括数据类型的定义和所有的functions@Bergi我已经完成了密码。“不做我想跳的事”这不是一个非常有用的问题描述。代码是做什么的?等效的python代码是什么样子的,以及Canopy中具体缺少了什么可以做同样的事情?给我们一些帮助来理解这个问题,那么我们就更有可能帮助您。@glennsl它就是这样做的:谢谢@O.O.Balance.This正在处理replacingChildren。你是对的,我没有提取子项-我只是使用了值。但我确实尝试了节点(使用
get
&mapChildrenAt
和append
)结果是完全不同的——它实际上将两棵树合并在一起:。我会再试一次,然后发布一个不同的问题。
module Main exposing (main)
import Canopy exposing (Node, append, children, get, leaf, node, value)
import Html exposing (Html, b, div, h1, h2, li, text, ul)
-- add a node (and its children) under a branch in another tree
tree1 : Node String
tree1 =
node "A-1"
[ node "A-1-1"
[ leaf "A-1-1-1"
, node "A-1-1-2"
[ leaf "A-1-1-2-1"
, leaf "A-1-1-2-2"
]
]
]
tree2 : Node String
tree2 =
node "B-1"
[ node "B-1-1"
[ leaf "B-1-1-1"
, node "B-1-1-2"
[ node "B-1-1-2-1"
[ leaf "don't remove me"
]
, leaf "B-1-1-2-2"
]
]
]
tree3 : Node String
tree3 =
let
nodeToMove =
Maybe.withDefault (leaf <| "Failed to find node " ++ "A-1-1") <| get "A-1-1" tree1
newParentNodeValue =
"B-1-1-2-1"
treeWithNewNode =
tree2 |> addNodeAt nodeToMove newParentNodeValue
in
treeWithNewNode
-- treeWithNewNode
main =
div []
[ h1 [] [ text "Adding a branch to another tree" ]
, h2 [] [ text "Tree 1" ]
, viewNode tree1
, h2 [] [ text "Tree 2" ]
, viewNode tree2
, h2 [] [ text "Move A-1-1 under B-1-1-2-1" ]
, viewNode tree3
]
viewNode : Node String -> Html msg
viewNode node =
let
subNodes =
children node
in
li []
[ b [] [ text (value node) ]
, ul [] (List.map viewNode subNodes)
]
addNodeAt : Node String -> String -> Node String -> Node String
addNodeAt node firstParentNodeValue toTree =
--Canopy.toList ->
-- [("A-1-1",Nothing),("A-1-1-1",Just "A-1-1"),("A-1-1-2",Just "A-1-1"),...]
node
|> Canopy.toList
|> List.foldl
-- acc is the updated toTree
(\( nodeValue, parentValue ) acc ->
append
(Maybe.withDefault firstParentNodeValue parentValue)
nodeValue
acc
)
-- initial value
toTree