gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 00:43:20 25 4
gpt4 key购买 nike

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

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

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com