Clojure:从嵌套列表中分离特定元素
Clojure: Separating a particular element from a nested list
我目前正在处理列表。我目前正在研究一个函数,它使用递归来遍历我创建的(或任何)嵌套列表结构。试图将数字与此结构中的其他元素分开。分开我的意思是将它们添加到一个空列表并将它们作为函数输出。
例如:
(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)
这是一个简单的解决方案:
(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 并始终打开浏览器标签。研究函数并全部练习。享受吧!
这是我的解决方案:
(defn tree->nums [tree]
(->> tree flatten (filter number?))
(tree->nums my-tree)
Clojure 中的这种数据操作 been a problem long enough that someone 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]
Spectre 几年前首次发布,最近获得了关注和关注。
由于到目前为止 none 的答案使用了递归,您在问题中提到了这一点,因此我将加入递归解决方案。
(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]
如果你想重新使用递归树遍历逻辑来查找除数字以外的其他东西,你可以编写一个函数,它接受一个谓词(一个 returns 布尔值的函数)和 returns 树行者。
;; 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]
我目前正在处理列表。我目前正在研究一个函数,它使用递归来遍历我创建的(或任何)嵌套列表结构。试图将数字与此结构中的其他元素分开。分开我的意思是将它们添加到一个空列表并将它们作为函数输出。
例如:
(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)
这是一个简单的解决方案:
(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 并始终打开浏览器标签。研究函数并全部练习。享受吧!
这是我的解决方案:
(defn tree->nums [tree]
(->> tree flatten (filter number?))
(tree->nums my-tree)
Clojure 中的这种数据操作 been a problem long enough that someone 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]
Spectre 几年前首次发布,最近获得了关注和关注。
由于到目前为止 none 的答案使用了递归,您在问题中提到了这一点,因此我将加入递归解决方案。
(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]
如果你想重新使用递归树遍历逻辑来查找除数字以外的其他东西,你可以编写一个函数,它接受一个谓词(一个 returns 布尔值的函数)和 returns 树行者。
;; 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]