首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >谓词为true的集合中除最后一个元素外的所有元素的序列

谓词为true的集合中除最后一个元素外的所有元素的序列
EN

Stack Overflow用户
提问于 2016-03-28 06:20:05
回答 2查看 230关注 0票数 0

我在编写优雅的drop-last-bybutlast-by函数时遇到了麻烦。

代码语言:javascript
复制
(drop-last-by odd? [2 1 9 4 7 7 3])  ; => (2 1 9 4)
(drop-last-by odd? [2 4])  ; => (2 4)
(drop-last-by odd? [9])  ; => ()

到目前为止,我所做的一切都很好用,但看起来有点笨拙,我想知道是否可以只用两三行代码就能完成。

代码语言:javascript
复制
(defn drop-last-by [pred coll]
  (let [p (partition-by pred coll)]
    (apply concat (if (and (seq p) (pred (first (last p))))
                    (butlast p)
                    p))))
EN

回答 2

Stack Overflow用户

发布于 2016-03-28 07:31:42

由于drop-while基本上已经完成了您所需的工作,并且您当前的解决方案已经不是懒惰的,因此我将drop-last-by编写为:

代码语言:javascript
复制
(defn drop-last-by [pred coll]
  (reverse (drop-while pred (reverse coll))))
票数 5
EN

Stack Overflow用户

发布于 2016-04-01 07:06:42

下面的版本懒惰到了问题规范所允许的程度:

  1. 不满足谓词的任何元素都会立即传递,而不会从源中读取任何其他元素;
  2. 只要从源读入不满足谓词的元素,就会传递满足该谓词的任何元素;
  3. 会删除满足该谓词且后面没有其他不满足该谓词的元素的任何元素。

此外,它还可以用作(有状态的)转换器;实际上,延迟序列版本是根据转换器和clojure.core/sequence实现的。

代码语言:javascript
复制
(defn drop-last-by
  ([pred]
   (fn [rf]
     (let [xs (volatile! [])]
       (fn
         ([] (rf))
         ([result] (rf result))
         ([result input]
          (if-not (pred input)
            (do
              (reduce rf result @xs)
              (vreset! xs [])
              (rf result input))
            (do
              (vswap! xs conj input)
              result)))))))
  ([pred coll]
   (sequence (drop-last-by pred) coll)))

在REPL:

代码语言:javascript
复制
(drop-last-by odd? [2 1 9 4 7 7 3])
;= (2 1 9 4)
(drop-last-by odd? [2 4])
;= (2 4)
(drop-last-by odd? [9])
;= ()

与其他传感器组成:

代码语言:javascript
复制
(into []
      (comp (drop-while even?)
            (drop-last-by odd?)
            (map #(str "foo " %)))
      [0 1 2 3 4 5])
;= ["foo 1" "foo 2" "foo 3" "foo 4"]
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36253375

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档