在 clojure 中压缩序列

Compress sequence in clojure

我正在尝试解决 http://www.4clojure.com/problem/30 并最终得到以下代码:

(fn [a] reduce #(if (= (last %1) %2) %1 (concat %1 (seq %2))) (empty a) (seq a))

我们的想法是,如果符号不等于当前结果字符串的最后一个符号,则将它们一个接一个地附加。但出于某种原因,我没有看到它 returns 与其输入相同的序列。

>((fn [a] reduce #(if (= (last %1) %2) %1 (concat %1 (seq %2))) (empty a) (seq a)) "Leeeeroy") (\L \e \e \e \e \r \o \y)

我尝试评估不同的子表达式,例如 (= (first (seq "Lee")) (last (seq "L"))) 他们似乎是正确的。有人能指出这个函数有什么问题吗?

首先,你的函数在很多方面都不对。当你定义一个匿名函数时,我猜你想放置一个 reduce 形式,但你实际上最终顺序放置了一个函数 reduce,然后是另一个匿名函数`#(if ...),等等.

修复此问题后,您会发现代码中出现了一些新错误,希望您以后可以解决这些问题。 :)

  • 你没有在 ( ... ) 中包装你的 reduce 表单,所以得到了值 最后一种形式,(seq a)。顺便说一下,seq 调用是多余的。
  • 您在 (concat %1 (seq %2)) 中使用 seq 是错误的。 seq 序列 一个集合;它不会从元素中生成序列。
  • 您想要一个空序列作为 reduce 的初始值。 有比 (empty a).
  • 更简单的表达方式

如果你纠正了这些错误,它就会起作用。但是你会发现它在长序列中慢得像爬行一样。原因是 last 通过每个元素的累积解决方案运行。查看其他解决方案以了解如何避免这种情况。

使用 partition-allremovefiltermap 有一个相当简洁的解决方案。