2017-03-03 55 views
0

我目前正在处理列表。我正在使用递归遍历我创建的嵌套列表结构(或任何)的函数。试图从这个结构中的数字与其他元素分开。分开我的意思是将它们添加到一个空的列表,并将它们作为函数输出。Clojure:从嵌套列表中分离特定元素

例如:

(def my-tree 
'(3 (apple) -2 (50 orange) 9 banana)) 

(defn function [my-tree] 
    if list is empty then return nil. 

if not then search through the list and append all numbers to an empty list. 

) 

user => (function my-tree) 
(3 -2 50 9) 
+0

你知道递归吗? – Jeremy

回答

1

这里有一个简单的解决方案:

(def my-tree 
    '(3 (apple) -2 (50 orange) 9 banana)) 

(def flat-tree (flatten my-tree)) 

(def nums (filter number? flat-tree)) 
(def syms (filter symbol? flat-tree)) 

flat-tree => (3 apple -2 50 orange 9 banana) 
nums => (3 -2 50 9) 
syms => (apple orange banana) 

你应该保存书签to The Clojure CheatSheet,始终保持一个浏览器标签页中打开它。研究功能并将它们全部实践。请享用!

+0

非常感谢Alan。扁平化功能正是我所需要的。我也发现了juxt,这会有所帮助。我意识到,在来这里之前,没有阅读clojure文档有点草率,尽管我仍然感激你花时间指引我走向正确的方向。 – DeltaForce

1

这里是我的解决方案:

(defn tree->nums [tree] 
    (->> tree flatten (filter number?)) 

(tree->nums my-tree) 
0

这Clojure中的各种数据处理的具有been a problem long enoughsomeone much smarter than I写的很通俗图书馆轻松高效地解决这类问题(远胜)。

以下是如何与幽灵解决这个问题:

user> (def my-tree 
     '(3 (apple) -2 (50 orange) 9 banana)) 
#'user/my-tree 
user> (use 'com.rpl.specter) 
nil 

user> (select (walker number?) my-tree) 
[3 -2 50 9] 

斯佩克特首次发布前几年和最近获得的牵引力和关注。

0

由于迄今为止答案都没有使用递归,你在问题中提到了,我会用递归解决方案作为参考。

(def my-tree 
    '(3 (apple) -2 (50 orange) 9 banana)) 

(defn tree-nums-helper 
    [acc tree] 
    (cond 
    ;; If tree is a collection, reduce tree-nums-helper over it using the 
    ;; current acc as the initial value. 
    (coll? tree) (reduce tree-nums-helper acc tree) 

    ;; So, tree is not a collection, it's a leaf. 
    ;; If it's a number, add it to the accumulator. 
    (number? tree) (conj acc tree) 

    ;; Else, just return the accumulator untouched. 
    :else acc)) 

(defn tree-nums 
    "Takes a tree and returns a vector of the numbers it contains 
    in depth first order." 
    [tree] 
    ;; Just calls the helper with an empty accumulator. 
    (tree-nums-helper [] tree)) 


(tree-nums my-tree) ;=> [3 -2 50 9] 

如果你想重新使用递归遍历树的逻辑来找到其他的事情不是数字,你可以写一个函数,一个谓词(即返回布尔函数),并返回一个树行者。

;; dfs = depth first search 

(defn dfs-factory [pred] 
    ;; You can name anonymous functions so that you can recursively 
    ;; refer to them from within themselves 
    (fn dfs 
    ([tree] 
    (dfs [] tree)) 

    ;; Instead of having a helper fn, here we have an extra arity. 
    ([acc tree] 
    (cond 
     (coll? tree) (reduce dfs acc tree) 
     (pred tree) (conj acc tree) 
     :else acc)))) 

(def tree-nums 
    (dfs-factory number?)) 

(tree-nums my-tree) ;=> [3 -2 50 9] 

(def tree-syms 
    (dfs-factory symbol?)) 

(tree-syms my-tree) ;=> [apple orange banana]