在Clojure中获取最嵌套的列表

时间:2016-08-07 10:16:14

标签: clojure

我正在将一些LISP功能迁移到Clojure。我对StackOverflow消息有以下功能的问题:

(defn m
    [list depth]
    (cond 
        (= list nil) depth
        (atom (first list)) (m (rest list) depth)
        (> (m (first list) (+ depth 1)) (m (rest list) depth))  (m (first list) (+ depth 1))
        :default (m (rest list) depth))
    )

(defn n
  [list depth maxdepth]
    (cond 
        (= list nil) nil
        (= depth maxdepth) list
        (atom (first list)) (n (rest list) depth maxdepth)
        (= 0 (n (first list) (+ depth 1) maxdepth)) (n (last list) depth maxdepth)
        :default (n (first list) (+ depth 1) maxdepth))
    )

(defn myfind[mylist]
    (n mylist 0 (m mylist 0))
)

我基本上想要的是最嵌套列表的输出,如:

(myfind '(1 2 3 (4 5) 6 ((7 8) 9)))
=> (7 8)

目标是使用递归并最小化内置函数的使用来实现这一点。

这种情况有什么问题?

3 个答案:

答案 0 :(得分:0)

(defn- deepest-with-depth [depth s]
  (let [nested-colls (filter coll? s)]
    (if (seq nested-colls)
      (mapcat (partial deepest-with-depth (inc depth)) nested-colls)
      [[depth s]])))

(defn deepest [s]
  (->> (deepest-with-depth 0 s)
       (apply max-key first)
       second))

> (deepest '(1 2 3 (4 5) 6 ((7 8) 9)))
(7 8)

如果它们与您的要求发生冲突,请随意将某些函数调用(例如max-keypartial)替换为其实现。

答案 1 :(得分:0)

(defn- max-depth-entry [a-list]
  (let [sub-lists (filter coll? a-list)
        [depth list] (if (empty? sub-lists)
                           [0 a-list]
                           (apply max-key first (map max-depth-entry sub-lists)))]
    [(inc depth) list]))

(max-depth-entry '(1 2 3 (4 5) 6 ((7 8) 9)))
;[3 (7 8)]

然后

(def max-depth-sublist (comp second max-depth-entry))

(max-depth-sublist '(1 2 3 (4 5) 6 ((7 8) 9)))
;(7 8)

我的想法是max-key使用OlegTheCat's answer。我最初使用reduce

编织自己的
(defn- max-depth-entry [a-list]
  (let [sub-lists (filter coll? a-list)
        [a-list a-depth] (reduce
                          (fn ([] [a-list 0])
                            ([[as an :as asn] [s n :as sn]] (if (> n an) sn asn)))
                          (map max-depth-entry sub-lists))]
    [a-list (inc a-depth)]))

然后

(def max-depth-sublist (comp first max-depth-entry))

现在我已经准备好回到Sequs Horribilis on 4Clojure,直到现在一直困扰着我。

答案 2 :(得分:0)

这里还有一个变种,只有经典的旧学校解决方案,而且根本没有特定的clojure序列功能:

(defn deepest [items depth]
  (if (sequential? items)
    (let [[it1 d1 :as res1] (deepest (first items) (inc depth))
          [it2 d2 :as res2] (deepest (next items) depth)]
      (cond (>= depth (max d1 d2)) [items depth]
            (>= d1 d2) res1
            :else res2))
    [items -1]))

它的嵌套列表递归的经典方法也值得注意:首先你重复car,然后再cdr,然后结合这些结果。

user> (deepest '(1 2 3 (4 5) 6 ((7 8) 9)) 0)
[(7 8) 2]

user> (deepest '(1 2 3 (4 5) 6) 0)
[(4 5) 1]

user> (deepest '(1 2 3 (x ((y (z)))) (4 5) 6) 0)
[(z) 4]

user> (deepest '(1 2 3 (x ((y (z)))) (4 5 ((((((:xxx)))))))) 0)
[(:xxx) 7]

user> (deepest '(1 2 3 ((((((((nil)))))))) (x ((y (z)))) (4 5) 6) 0)
[(nil) 8]

user> (deepest '(1 2 3) 0)
[(1 2 3) 0]