2017-03-03 54 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]