clojure 中的地图给出了意想不到的结果

mad*_*ant 2 dictionary clojure

在clojure中使用map,检查字符串是否包含大写字符。

(map #(= (clojure.string/upper-case %) %) "Hello") 
Run Code Online (Sandbox Code Playgroud)

预期的结果。

(true false false false false)
Run Code Online (Sandbox Code Playgroud)

不幸的是,结果出乎意料。

(false false false false false)
Run Code Online (Sandbox Code Playgroud)

我做了一个实验,当我在第一个“%”中替换“H”时,结果仍然出乎意料。

(map #(= (clojure.string/upper-case "H") %) "Hello") 

(false false false false false)
Run Code Online (Sandbox Code Playgroud)

当我在第二个“%”中替换“H”时,结果发生了变化,这是预期的结果。

(map #(= (clojure.string/upper-case %) "H) "Hello") 

(true false false false false)
Run Code Online (Sandbox Code Playgroud)

那有什么问题?请随意发表评论。

Ste*_*ott 8

正如其他人指出的那样,将字符与字符串进行比较是行不通的。比较字符串将起作用:

(map #(= (clojure.string/upper-case %) (str %)) "Hello")
=> (true false false false false)
Run Code Online (Sandbox Code Playgroud)

然而,这更直接:

(map #(Character/isUpperCase %) "Hello")
=> (true false false false false)
Run Code Online (Sandbox Code Playgroud)


小智 6

您不能将 String 与 char 进行比较。由字符串组成的序列是一个字符列表。

(seq "Hello")
;; => (\H \e \l \l \o)
(map class "Hello")
;; => (java.lang.Character java.lang.Character java.lang.Character java.lang.Character java.lang.Character)
Run Code Online (Sandbox Code Playgroud)

所以在你的情况下,你的测试归结为

(= "H" \H) ;; => false
Run Code Online (Sandbox Code Playgroud)

这是错误的。

要使其工作,请尝试以下操作之一:

;; compare strings
(map #(= (clojure.string/upper-case %) (str %)) "Hello")
;; => (true false false false false)

;; compare chars
(map #(= (first (clojure.string/upper-case %)) %) "Hello")
;; => (true false false false false)
Run Code Online (Sandbox Code Playgroud)


Gwa*_*Kim 6

这是因为您错误地假设map将字符串"Hello"分解为,("H" "e" "l" "l" "o")但事实并非如此!

尝试:

(map identity "Hello") ;; => (\H \e \l \l \o)
Run Code Online (Sandbox Code Playgroud)

因此 map 将字符串分解为字符列表而不是单个字符串的列表。

所以你(map #(= (clojure.string/upper-case %) %) "Hello")正在比较 (clojure.string/upper-case \H)哪个结果"H"与\H. 由于一个是单个字符串,另一个是字符,结果是false- 因为类型不同。

(map #(= (clojure.string/upper-case %) (str %)) "Hello")
Run Code Online (Sandbox Code Playgroud)

但是,您对原始代码的期望是什么。它返回:

(true false false false false)
Run Code Online (Sandbox Code Playgroud)

功能

最有效的方法可能是使用正则表达式:

(defn has-upper-case? [s] (boolean (re-find #"[A-Z]" s)))

Run Code Online (Sandbox Code Playgroud)

不太严格(不返回布尔值,而是从左到右的字符串的第一个上单字符串,或者nil如果没有找到):

(defn has-upper-case? [s] (re-find #"[A-Z]" s))
Run Code Online (Sandbox Code Playgroud)

  • @madeinQuant 使用正则表达式的要点是它使“map”变得多余。一旦看到字符串中的第一个大写字符,“re-find”就会停止扫描。然后不再检查其他字符 -> 从而有助于性能。因此,当使用正则表达式时,您可以一次输入整个字符串 - 一旦找到第一个匹配项,扫描就会结束。 (2认同)