algorithm - Clojure:在字符串中查找 "1"的位置,并以区间的格式打印出来

标签 algorithm clojure

我正在尝试解决这样的问题:

给定一个由“1”和“0”组成的字符串,找到“1”的所有位置,并以区间的形式打印出来。

例如: "00101110101110"=> 3, 5-7, 9, 11-13

我的(丑陋的)解决方案:

(defn bar [x]
  (letfn [(foo [mystr]
            (->>
              (map-indexed vector mystr)
              (filter #(= (second %) \1))
              (map (comp inc first))
              (partition-all 2 1)
              (filter #(= 2 (count %)))))]
    (let [y (map #(if (> (- (second %) (first %)) 1) (print (first %) ", " (second %) "-")) (foo x))]
      (print (ffirst y) "-" y (last (last (foo x)))))))

解释:

首先,我在给定的字符串中找到“1”的位置:

(->>
    (map-indexed vector mystr)
    (filter #(= (second %) \1))
    (map (comp inc first)))

"00101110101110"=> (3 5 6 7 9 11 12 13)

然后,我将位置列表划分为一系列 2 元素元组。如果在该序列的末尾有一个 1 元素元组,则将其删除:

  (->>
    (map-indexed vector mystr)
    (filter #(= (second %) \1))
    (map (comp inc first))
    (partition-all 2 1)
    (filter #(= 2 (count %))))

"00101110101110"=> ((3 5) (5 6) (6 7) (7 9) (9 11) (11 12) (12 13))

最后,我打印出第一个元组中的第一个位置和最后一个元组中的第二个位置,同时使用 (map #(if (> (- (second %) (first %)) 1) (print (first %) ", "(second %) "-")) (foo x))得到中间部分。

输入: (栏“00101110101110”)

最终结果: 3, 5 -nil - (nil nil 7, 9 -nil 9, 11 -nil nil nil nil) 13

我的问题:

  1. 如何去除最终结果中的nil
  2. 如何以更简洁的方式解决这个问题?

最佳答案

为了了解如何从最终结果中删除 nil,让我们首先了解它们是如何进入的。在最后一个 let 形式中绑定(bind)到名称 y 的值实际上是所有 nil 值的序列。函数 bar 本身也返回 nil。发生这种情况是因为 print 总是返回 nilif 在条件为假和“else”形式时返回 nil不存在。实际上,foo 返回的序列中的每个值都被转换为 nil。输出中的非零值是作为副作用打印的值。 nil 和非 nil 值混合是因为 map 是惰性的,只有在最后一个 print 实现惰性序列时才应用映射函数 y。不用说,为副作用使用 map 是个坏主意。

因此,从输出中删除 nil 的最简单方法是完全避免使用 nil 值。

(->> "00101110101110"
  (map-indexed vector)                         ;; ([0 \0] [1 \0] [2 \1]...
  (partition-by second)                        ;; (([0 \0] [1 \0]) ([2 \1]) ([3 \0]) ([4 \1] [5 \1] [6 \1]) ...
  (filter #(= \1 (-> % first second)))         ;; (([2 \1]) ([4 \1] [5 \1] [6 \1])...
  (map #(map (comp inc first) %))              ;; ((3) (5 6 7) (9) (11 12 13))
  (map #(if (next %) [(first %) (last %)] %))  ;; ((3) [5 7] (9) [11 13])
  (map #(clojure.string/join "-" %))           ;; ("3" "5-7" "9" "11-13")
  (clojure.string/join ", "))
;; => "3, 5-7, 9, 11-13"

关于algorithm - Clojure:在字符串中查找 "1"的位置,并以区间的格式打印出来,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27613545/

相关文章:

Clojure:使用 assoc-in 的结果不一致

clojure - 如何在 clojure 中实习宏?

clojure - 大量的defrecord导致 "Method code too large"

clojure - 使用和要求之间的区别

concurrency - 了解 Clojure 并发示例

algorithm - 带边缘移除的寻路 : multiple paths to a destination,

algorithm - DAG 路径乘积之和

actionscript-3 - 如何更好地为 3D 画廊打包与球体相切的矩形?

algorithm - 将 u32 映射到指针的低开销方案

java - Java中的朴素后缀树实现