clojure.lang.LazySeq无法强制转换为java.lang.CharSequence

时间:2018-01-27 02:10:30

标签: clojure

我正在编写一个函数,对于任何给定的字符串,用相同数量的'替换该字符串中的任何数字。'字符。

示例:

AT2X - > AT..X

QW3G45 - > QW ...ģ.........

T3Z1 - > Ť... Z

我已经写了以下Clojure功能,但我收到的错误我不太明白:

java.lang.ClassCastException:clojure.lang.LazySeq(在模块中:未命名的模块)不能成为java.lang.Charsequence的案例

我从错误中解释我需要强制将懒惰序列评估回String(或CharSequence),但我无法弄清楚在哪里这样做或者这是否正确。

(defn dotify
    ;;Replaces digits with the same number of '.'s for use in traditional board formats
    [FEN]
    (let [values (doall (filter isDigit (seq FEN)))]
        (fn [values]
            (let [value (first values)]
                (str/replace FEN value (fn dots [number]
                                           (fn [s times]
                                               (if (> times 0)
                                                   (recur (str s ".") (dec times)))) "" (Character/digit number 10)) value))
        (recur (rest values))) values))

2 个答案:

答案 0 :(得分:2)

有一个标准的clojure.string/replace函数可以处理这种情况。它的最后一个参数可能不仅仅是一个字符串或一个模式,而且还是一个将找到的片段转换成你想要的片段的函数。

让我们先准备好这样一个功能:

(defn replacer [sum-str]
  (let [num (read-string num-str)]
    (apply str (repeat num \.))))

你可以这样试试:

user> (replacer "2")
..
user> (replacer "9")
.........
user> (replacer "22")
......................
user> 

现在将其传递到replace,如下所示:

user> (clojure.string/replace "a2b3c11" #"\d+" replacer)
a..b...c...........

答案 1 :(得分:0)

以下是使用fig = plt.figure(figsize=(6,6)) gs = gridspec.GridSpec(2, 2) gs.update(left=0, wspace=0) ax1 = plt.subplot(gs[0]) ax1.plot(data_1, 's') ax1.axis('off') ax2 = plt.subplot(gs[1]) ax2.plot(data_2, 's') ax2.axis('off') ax3 = plt.subplot(gs[2]) ax3.plot(data_3, 's') ax3.axis('off') ax4 = plt.subplot(gs[3]) ax4.plot(data_4, 's') ax4.axis('off') plt.savefig(os.path.join(cwd, 'data/%d.png' % index), bbox_inches='tight', pad_inches=0, dpi=20) plt.close()

执行此操作的方法
reduce

使用(defn dotify [s] (->> s (reduce (fn [acc elem] (if (Character/isDigit elem) (let [dots (Integer/parseInt (str elem))] (apply conj acc (repeat dots \.))) (conj acc elem))) []) (apply str))) (dotify "zx4g1z2h") => "zx....g.z..h" 的另一个版本:

mapcat

您的示例中存在一些问题:

  1. 许多内部表单本身就是函数,但看起来你只需要它们的主体或实现,而不是将它们包装在函数中。
  2. 很难用缩进/空格来表示,但是整个函数只是(defn dotify-mapcat [s] (apply str (mapcat (fn [c] (if (Character/isDigit c) (repeat (Integer/parseInt (str c)) \.) [c])) s))) - ,它上面的recur没有被使用或返回。
  3. fn的一个参数是一个返回函数的函数。
  4. 有助于将问题分解成更小的部分。首先,您知道您需要检查字符串中的每个字符,并决定是将其返回还是将其扩展为一系列点。所以你可以从一个函数开始:

    str/replace

    然后在高阶函数中使用对一个字符一次操作的函数,该函数对整个字符串进行操作:

    (defn expand-char [^Character c]
      (if (Character/isDigit c)
        (repeat (Integer/parseInt (str c)) \.)
        [c]))
    

    请注意,由于(apply str (mapcat expand-char s)) => "zx....g.z..h" 函数中的^Character类型提示,这比上面的示例快〜5倍。

    您也可以使用expand-char执行此操作:

    str/replace