【问题标题】:Clojure manipulate sequence of stringsClojure 操作字符串序列
【发布时间】:2013-08-22 12:44:33
【问题描述】:

我有一个["a" "b" " c" "d" " e" " f" "g"] 形式的数据结构

我想将其简化为["a" "b c" "d e f" "g"],也就是说,以空格开头的字符串连接到它们前面的字符串。

我已经为此苦苦挣扎了几个小时,正在寻找一些灵感!

【问题讨论】:

  • 向我们展示你到目前为止所得到的东西
  • 我意识到我需要使用reduce,然后碰到了一点砖墙。这些最初的答案都非常有创意,所以我会在选择之前与他们一起玩。

标签: vector clojure reduce


【解决方案1】:

这会将字符串序列拆分为块,然后将所有应该连接的字符串组与每个组的单个 string/join 调用连接起来,因此它避免了解决方案将字符串一个一个粘贴在一起的二次行为:

(def xs ["a" "b" " c" "d" " e" " f" "g"])

(require '[clojure.string :as string])

(->> xs
     (partition-by #(.startsWith ^String % " "))
     (map vec)
     (partition-all 2)
     (reduce (fn [acc [ps ss]]
               (-> acc
                   (into (pop ps))
                   (conj (string/join "" (cons (peek ps) ss)))))
             []))
;= ["a" "b c" "d e f" "g"]

请注意,这假定第一个字符串不以空格开头。为了消除这种假设,您可以在前面添加一个空字符串((cons "" xs) 而不是上面的xs,或者(cons "") 作为第一个->> 步骤)来“捕获”它们。在这种情况下,结果将以一个字符串开头,该字符串由以空格开头的序列初始字符串连接在一起,或者如果序列不以此类字符串开头,则为一个空格,因此您可以检查"" 在结果中的第一个位置,并可能将其过滤掉。

【讨论】:

    【解决方案2】:

    过滤器和初始累加器处理第一个的混合方法从空间情况开始。

    (defn join-when-space [vs]
      (mapv (partial apply str) 
        (filter not-empty 
          (reduce (fn [a s] (if (re-find #"^\s" s) 
                              (conj (pop a) (conj (peek a) s)) 
                              (conj a [s]))) 
             [[]] vs))))
    

    【讨论】:

    • 感谢 A. 韦伯。所有的反应都是有创意的,性能明智的,在我的 Mac 上都无法区分,但我更喜欢你的角色经济。几乎不是一个负责任的指标,但你去吧!
    【解决方案3】:

    以下是使用reduce 的一种方法,尽管可能有一种更优雅的方法来做同样的事情 - Clojure 中经常有 :)

    (defn join-when-space [v]
       (->> (reduce (fn [acc next-value]
                       (if (re-matches #"^ .*" next-value)
                         (concat (butlast acc) [(str (last acc) next-value)])
                         (concat acc [next-value]))) 
                    [[] (first v)] (rest v))
             rest
             (into [])))
    

    【讨论】:

    • 同样的想法,更干净一点:(reduce (fn [a s] (if (re-find #"^\s" s) (conj (pop a) (str (peek a) s)) (conj a s))) [] ["a" "b" " c" "d" " e" " f" "g"])
    【解决方案4】:

    这个函数产生一个序列 strings 拼接在初始空格上的惰性序列:

    (defn spliced-seq [strings]
      (let [[x & xs] strings]
       (if (empty? xs)
        [x]
        (let [[ys & ns] (split-with #(.startsWith % " ") xs)]
          (cons (apply str x ys) (lazy-seq (f ns)))))))
    

    然后(vec (spliced-seq) ["a" " b" " c" "d" "e"])) 产生["a b c" "d e"]

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-25
      • 1970-01-01
      • 2011-05-12
      • 1970-01-01
      相关资源
      最近更新 更多