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

Clojure 谓词为true的集合中除最后一个元素外的所有元素的序列,clojure,Clojure,我在编写优雅的drop last by或butlast by函数时遇到问题 (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]) ; => () 到目前为止,我所做的工作很有效,但似乎有点笨拙,我想知道是否可以只用两三行就完成 (defn drop-last-by [pred coll] (let

我在编写优雅的
drop last by
butlast by
函数时遇到问题

(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])  ; => ()
到目前为止,我所做的工作很有效,但似乎有点笨拙,我想知道是否可以只用两三行就完成

(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))))
既然已经基本上满足了您的需求,而且您当前的解决方案已经不是懒惰的,那么我将像这样写
最后一个drop by

(defn drop-last-by [pred coll]
  (reverse (drop-while pred (reverse coll))))
既然已经基本上满足了您的需求,而且您当前的解决方案已经不是懒惰的,那么我将像这样写
最后一个drop by

(defn drop-last-by [pred coll]
  (reverse (drop-while pred (reverse coll))))

以下版本延迟到问题规范允许的程度:

  • 任何不满足谓词的元素都会立即被传递,而不会从源代码中读取任何附加元素

  • 一旦从源中读入不满足谓词的元素,任何满足谓词的元素都会被传递

  • 任何满足谓词且后面没有其他不满足谓词的元素的元素都将被删除

  • 此外,它还可用作(有状态)传感器;实际上,lazy-seq版本是根据传感器和
    clojure.core/sequence
    实现的

    (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上:

    (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])
    ;= ()
    
    由其他传感器组成:

    (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"]
    

    以下版本延迟到问题规范允许的程度:

  • 任何不满足谓词的元素都会立即被传递,而不会从源代码中读取任何附加元素

  • 一旦从源中读入不满足谓词的元素,任何满足谓词的元素都会被传递

  • 任何满足谓词且后面没有其他不满足谓词的元素的元素都将被删除

  • 此外,它还可用作(有状态)传感器;实际上,lazy-seq版本是根据传感器和
    clojure.core/sequence
    实现的

    (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上:

    (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])
    ;= ()
    
    由其他传感器组成:

    (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"]