Pythonでは、これを行うことができます:
>>> import string
>>> string.letters
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
Clojureで同様のことを行う方法はありますか(上記の文字をコピーしてどこかに貼り付けることは別として)?Clojure標準ライブラリとJava標準ライブラリの両方を調べましたが、見つかりませんでした。
アスキー文字だけが必要な場合は、
(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)
適切に非 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 文字よりもはるかに多くの文字を取得できると思います。
警告: 基本的な多言語面のみを考慮します。追加の飛行機に拡張するのはそれほど難しくありませんが、それにはもっと時間がかかり、有用性は疑問です.
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)
は非常に興味深いです。
いいえ、それはフルセットではなく ASCII 文字を出力しているだけだからです。もちろん、2 つの for ループを使用して 26 個の小文字と大文字を出力するのは簡単ですが、実際には、最初の 127 個のコード ポイントの外側にもっと多くの「文字」があります。Character に対する Java の「isLetter」fn は、これらおよびその他の多くの場合に当てはまります。
string.letters: 以下で説明する文字列の小文字と大文字の連結。特定の値はロケールに依存し、locale.setlocale() が呼び出されると更新されます。
Michael Borgwardt からの回答を修正しました。私の実装では、2 つの理由から、lowerCases と upperCases の 2 つのリストがあります。
string.letters は、小文字の後に大文字が続きます。
Java Character.isLetter(char)は大文字と小文字だけではないため、 Character.isLetter(char) を使用すると、「windows-1252」などの一部の文字セットで多くの結果が返されます。
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内でデフォルトの文字セットを変更できないと思います。したがって、string.letters の「ロケールの変更」動作は、Locale.setDefault(Locale) だけでは実現できません。しかし、デフォルトのロケールを変更することはとにかく悪い考えです:
デフォルトのロケールを変更すると、機能のさまざまな領域に影響を与える可能性があるため、このメソッドは、呼び出し側が同じ Java 仮想マシン内で実行されているロケールに依存するコードを再初期化する準備ができている場合にのみ使用してください。
手紙は標準ライブラリで利用できないと確信しているので、おそらく手動のアプローチが残っています。
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());
}
}
コードポイントの範囲を覚えていない場合。力ずくの方法 :-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>