如何在Clojure中获取序列的尾部

8

我有一个Clojure的序列。

(1 2 3 4) 

如何获取序列的所有尾部,例如:
((1 2 3 4) (2 3 4) (3 4) (4) ())
6个回答

14

使用reductions函数也可以获得所有尾部。

user=> (def x '(1 2 3 4))
#'user/x
user=> (reductions (fn [s _] (rest s)) x x)
((1 2 3 4) (2 3 4) (3 4) (4) ())
user=> 

4

如果你想使用更高级的函数来完成这个任务,我认为 iterate 很适合此处:

(defn tails [xs]
  (concat (take-while seq (iterate rest xs)) '(()))

但是在这种情况下,我认为最好使用lazy-seq来编写它:

(defn tails [xs]
  (if-not (seq xs) '(())
    (cons xs (lazy-seq (tails (rest xs))))))

感谢您的回复,结果为([1 2 3 4] (2 3 4) (3 4) (4) ()),为什么第一个是向量形式? - hariszaman
1
@hariszaman 这是因为 iterate 函数首先返回第二个参数本身,而没有应用函数。然后它开始应用 rest 函数,该函数返回一个 ChunkedSeq,其打印方式与列表相同。 - soulcheck

1
这是一种方法。
user=> (def x [1 2 3 4])
#'user/x
user=> (map #(drop % x) (range (inc (count x))))
((1 2 3 4) (2 3 4) (3 4) (4) ())

2
这段代码不应该用于懒序列,调用count会强制执行整个序列。 - noisesmith

1
一种方法是通过使用

标签来实现。

(defn tails [coll]
  (take (inc (count coll)) (iterate rest coll)))

3
这将强制执行任何懒惰的输入。 - noisesmith
是的,由于计数。我没有真正考虑过这个问题。 - turingcomplete

0
(defn tails
  [s]
  (cons s (if-some [r (next s)]
            (lazy-seq (tails r))
            '(()))))

哦。嘿。我猜我的 REPL 正在运行 1.5 版本。 - galdre
你如何在15秒内回复? - Leon Grapenthin
当你发表评论时,我正准备关闭我的SO窗口。 :-) - galdre

0

耶!又来了一个:

(defn tails [coll]
    (if-let [s (seq coll)]
        (cons coll (lazy-seq (tails (rest coll))))
        '(())))

这实际上就是 reductions 在幕后所做的事情。顺便说一下,最好的答案是 ez121sl's


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接