clojure - 如何从嵌套列表中删除元素?

标签 clojure

我有一个深度嵌套的列表,我想从列表中所有出现的给定元素中删除它。我有这段代码:

(defn eliminate [value lst]
            (defn sub-eliminate [lst]
              (def currentItem (first lst))
              (if-not (empty? lst)
                (if (seq? currentItem)
                  (cons (sub-eliminate currentItem) (sub-eliminate (rest lst)))
                  (if (= value currentItem)
                    (sub-eliminate (rest lst))
                    (cons currentItem (sub-eliminate (rest lst)))
                    )
                  )
                '()
                )
              )
              (sub-eliminate lst)
            )

但是,它不会在内部级别删除。为什么??

最佳答案

我的猜测是您将向量用作序列。

(eliminate 3 [3 3])
;()

(eliminate 3 [3 [3]])
;([3])

如果您向我们展示了一个例子,这将很容易找到:啧啧!


发生了什么事?

虽然向量是可序列化的,但它们不是序列:

(seq? [])
;false

在外层,您将 lst 视为一个序列,因此 firstrest 起作用,因为它们将参数包装在一个隐含的序列。但是 seq? 将在任何立即包含的向量上失败,甚至不会看到那些更远的向量。

如果将 seq? 替换为 sequential?,列表和向量将起作用。

(sequential? [])
;true

正如@noisesmith 指出的,更严重的是您在内部范围内使用了defdefn。将它们替换为 letletfn

您还可以改进您的风格:

  1. (if-not (empty? lst) ... ) 替换为 (if (seq lst) ...)
  2. 使用 cond 来展平嵌套的 if。这需要反相 (1) 中的测试,因此不需要它。
  3. 在找到 value 的尾递归情况下使用 recur,如 @Mark

如果你不想看到结果,现在就把目光移开:

(defn eliminate [value lst]
  (letfn [(sub-eliminate [lst]
            (let [current-item (first lst)]
              (cond
               (empty? lst) '()
               (sequential? current-item) (cons (sub-eliminate current-item) 
                                                (sub-eliminate (rest lst)))
               (= value current-item) (recur (rest lst))
               :else (cons current-item (sub-eliminate (rest lst))))))]
    (sub-eliminate lst)))

还有一个压痛点:

  • 在知道lst 不为空之前调用(first lst)。不 造成的伤害:你只会得到 nil,你会忽略它。

使用解构的替代方法

你可以经常使用destructuring缩写序列的递归处理。我倾向于这样表达你的功能:

(defn eliminate [x xs]
  ((fn rem-x [xs]
     (if-let [[y & ys] (seq xs)]
       (if (= x y)
         (recur ys)
         (cons
          (if (sequential? y) (rem-x y) y)
          (rem-x ys)))
       ()))
   xs))

关于clojure - 如何从嵌套列表中删除元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26175167/

相关文章:

interop - 在Clojure中动态访问Java字段?

ssl - Ring 是否请求 { :scheme :https} guarantee a HTTPS connection?

windows - Leiningen 终止批处理文件的执行

java - 从 clojure 调用带有可选 null 参数的 java 函数

clojure - 如何以类似于线程的方式在 clojure 中导航 map

clojure - 减少开发时的内存消耗

json - 如何将clojure代码映射到JSON?

function - 无法在 map 函数中捕获异常

http - 管理 HTTP 请求链的模式

variables - (部分 apply str)和 clojure 中的 apply-str ->