Clojure:将特定元素与嵌套列表分开

时间:2017-03-03 17:50:40

标签: clojure tree nested-lists

我目前正在制作名单。我正在研究一个函数,它使用递归来迭代我创建的嵌套列表结构(或任何)。试图将数字与此结构中的其他元素分开。通过单独我的意思是将它们添加到空列表并将它们作为函数输出。

例如:

(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)

4 个答案:

答案 0 :(得分: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,并始终打开浏览器标签。研究功能并实践它们。享受!

答案 1 :(得分:1)

这是我的解决方案:

// Cache Function
function cachestart($min){
    global $here;
    global $cachefile;
    $cachedosyasi = 'cache/' . 'file' . md5($here);
    if(file_exists($cachefile) && (time() - $min*60 < filemtime($cachefile))){
    include($cachefile);
    die;
    }else{
        ob_start();
        global $cache;
        $cache = 1;
    }
}

function cachefinish(){
    global $cache;
    global $cachefile;
    if(@$cache){
        $ch = fopen($cachefile, 'w');
        fwrite($ch, ob_get_contents());
        fclose($ch);
        ob_end_flush(); 
    }
}

答案 2 :(得分: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]
幽灵几年前首次发布,最近获得了关注和吸引力。

答案 3 :(得分: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]