在Python中,我可以这样做:
>>> import string
>>> string.letters
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
有没有办法在Clojure中做类似的事情(除了在某处复制和粘贴上面的字符)?我查看了Clojure标准库和java标准库,但找不到它。
答案 0 :(得分:20)
如果你只想要Ascii字符,
(map char (concat (range 65 91) (range 97 123)))
会产生,
(\A \B \C \D \E \F \G \H \I \J \K \L \M \N \O \P \Q \R \S \T \U \V \W \X \Y \Z
\a \b \c \d \e \f \g \h \i \j \k \l \m \n \o \p \q \r \s \t \u \v \w \x \y \z)
答案 1 :(得分:13)
正确的非以ASCII为中心的实现:
private static String allLetters(String charsetName)
{
CharsetEncoder ce = Charset.forName(charsetName).newEncoder();
StringBuilder result = new StringBuilder();
for(char c=0; c<Character.MAX_VALUE; c++)
{
if(ce.canEncode(c) && Character.isLetter(c))
{
result.append(c);
}
}
return result.toString();
}
用“US-ASCII”调用它,你将获得所需的结果(除了首先是大写字母)。您可以使用Charset.defaultCharset()
来调用它,但我怀疑您在大多数系统上获得的远远超过ASCII字母,即使在美国也是如此。
警告:只考虑基本的多语言平面。不会太难扩展到补充平面,但这需要更长的时间,并且效用值得怀疑。
答案 2 :(得分:6)
基于Michaels命令式Java解决方案,这是一个惯用的(懒惰序列)Clojure解决方案:
(ns stackoverflow
(:import (java.nio.charset Charset CharsetEncoder)))
(defn all-letters [charset]
(let [encoder (. (Charset/forName charset) newEncoder)]
(letfn [(valid-char? [c]
(and (.canEncode encoder (char c)) (Character/isLetter c)))
(all-letters-lazy [c]
(when (<= c (int Character/MAX_VALUE))
(if (valid-char? c)
(lazy-seq
(cons (char c) (all-letters-lazy (inc c))))
(recur (inc c)))))]
(all-letters-lazy 0))))
<强>更新强> 感谢cgrand这个更好的高级解决方案:
(defn letters [charset-name]
(let [ce (-> charset-name java.nio.charset.Charset/forName .newEncoder)]
(->> (range 0 (int Character/MAX_VALUE)) (map char)
(filter #(and (.canEncode ce %) (Character/isLetter %))))))
但是我的第一种方法之间的性能比较
user> (time (doall (stackoverflow/all-letters "ascii")))
"Elapsed time: 33.333336 msecs"
(\A \B \C \D \E \F \G \H \I \J \K \L \M \N \O \P \Q \R \S \T \U \V \W \X \Y \Z \\
a \b \c \d \e \f \g \h \i \j \k \l \m \n \o \p \q \r \s \t \u \v \w \x \y \z)
和你的解决方案
user> (time (doall (stackoverflow/letters "ascii")))
"Elapsed time: 666.666654 msecs"
(\A \B \C \D \E \F \G \H \I \J \K \L \M \N \O \P \Q \R \S \T \U \V \W \X \Y \Z \\
a \b \c \d \e \f \g \h \i \j \k \l \m \n \o \p \q \r \s \t \u \v \w \x \y \z)
非常有趣。
答案 3 :(得分:5)
不,因为那只是打印出ASCII字母而不是全套字母。当然,使用两个for循环打印26个小写字母和大写字母是微不足道的,但事实是在前127个代码点之外还有更多的“字母”。 Java中的“isLetter”字符对于这些和其他许多人都是正确的。
答案 4 :(得分:3)
string.letters: 字符串小写和大写的串联描述 下面。具体的价值是 区域设置依赖,并将更新 当调用locale.setlocale()时。
我修改了Michael Borgwardt的答案。在我的实现中,有两个列表lowerCases和upperCases有两个原因:
string.letters是小写,后跟大写。
Java Character.isLetter(char)不仅仅是大写和小写,因此使用Character.isLetter(char)会在某些字符集下返回很多结果,例如“windows-1252”
< / LI> 醇>来自Api-Doc: Character.isLetter(char):
一个角色被认为是一个角色 字母如果是一般类别类型, 由Character.getType(ch)提供,是 以下任何一项:
* UPPERCASE_LETTER * LOWERCASE_LETTER * TITLECASE_LETTER * MODIFIER_LETTER * OTHER_LETTER
并非所有信件都有案例。许多 字符是字母但不是 大写,小写,也不是标题。
因此,如果string.letters只返回小写和大写,那么TITLECASE_LETTER, ,MODIFIER_LETTER和OTHER_LETTER字符必须被忽略。
public static String allLetters(final Charset charset) {
final CharsetEncoder encoder = charset.newEncoder();
final StringBuilder lowerCases = new StringBuilder();
final StringBuilder upperCases = new StringBuilder();
for (char c = 0; c < Character.MAX_VALUE; c++) {
if (encoder.canEncode(c)) {
if (Character.isUpperCase(c)) {
upperCases.append(c);
} else if (Character.isLowerCase(c)) {
lowerCases.append(c);
}
}
}
return lowerCases.append(upperCases).toString();
}
<强>此外:强> 更改语言环境时string.letters的行为会发生变化。这可能不适用于我的解决方案,因为更改默认语言环境不会更改默认字符集。来自apiDoc:
确定默认字符集 在虚拟机启动过程中 通常取决于区域设置和 基础操作的字符集 系统
我想,在启动的JVM中无法更改默认字符集。因此,仅使用Locale.setDefault(Locale)无法实现string.letters的“更改区域设置”行为。但是更改默认语言环境无论如何都是一个坏主意:
由于更改默认语言环境可能 影响许多不同的领域 功能,这个方法应该只 如果呼叫者准备好,则使用 重新初始化区域设置敏感的代码 在同一个Java Virtual中运行 机。
答案 5 :(得分:1)
我很确定这些字母在标准库中不可用,因此您可能只需要手动方法。
答案 6 :(得分:1)
与Python解决方案相比,必须手动生成以下语句,与您的问题中提到的结果相同:
public class Letters {
public static String asString() {
StringBuffer buffer = new StringBuffer();
for (char c = 'a'; c <= 'z'; c++)
buffer.append(c);
for (char c = 'A'; c <= 'Z'; c++)
buffer.append(c);
return buffer.toString();
}
public static void main(String[] args) {
System.out.println(Letters.asString());
}
}
答案 7 :(得分:1)
如果您不记得代码点范围。蛮力方式:-P:
user> (require '[clojure.contrib.str-utils2 :as stru2])
nil
user> (set (stru2/replace (apply str (map char (range 0 256))) #"[^A-Za-z]" ""))
#{\A \a \B \b \C \c \D \d \E \e \F \f \G \g \H \h \I \i \J \j \K \k \L \l \M \m \N \n \O \o \P \p \Q \q \R \r \S \s \T \t \U \u \V \v \W \w \X \x \Y \y \Z \z}
user>