Когда у меня болит мозг, потому что он застрял в дереве, я стараюсь говорить то, что хочу, как можно проще и яснее:
- Учитывая дерево информации, перечислите все поддеревья, соответствующие предикату (в данном случае, info = 3).
Один простой способ сделать это - перечислить все узлы дерева, а затем отфильтровать предикат.
type 'info tree = Node of 'info * 'info tree list
let rec visit = function
| Node( info, [] ) as node -> [ node ]
| Node( info, children ) as node -> node :: List.collect visit children
let filter predicate tree =
visit tree
|> List.filter (fun (Node(info,_)) -> predicate info)
Вот фильтр дерева, работающий с образцами данных OP:
let result = filter (fun info -> info = 3) test
Одна вещь, которая удивила меня, это то, как легко код работает для любого типа информации с соответствующим предикатом:
let test2 =
Node(("One",
[Node("Two",
[Node("Three",[Node("Five",[]);Node("Three",[])]);
Node("Three",[])]);
Node("Three",[])]))
let res2 = filter (fun info -> info = "Three") test2
В качестве альтернативы, если вы хотите перечислить информацию, а не поддеревья, код просто потрясающий:
let rec visit = function
| Node( info, [] ) -> [ info ]
| Node( info, children ) -> info :: List.collect visit children
let filter predicate tree =
visit tree
|> List.filter predicate
, который поддерживает те же запросы, но возвращает только информационные записи, а не древовидную структуру:
let result = filter (fun info -> info = 3) test
> val result : int list = [3; 3; 3; 3]