代码之家  ›  专栏  ›  技术社区  ›  Jason Baker

如何获得Java/Clojure中所有字母的集合?

  •  11
  • Jason Baker  · 技术社区  · 16 年前

    在Python中,我可以做到:

    >>> import string
    >>> string.letters
    'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    

    在Clojure中有没有类似的方法(除了复制和粘贴上面的字符之外)?我浏览了Clojure标准库和java标准库,却找不到它。

    8 回复  |  直到 16 年前
        1
  •  14
  •   Michael Borgwardt    16 年前

    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
  •  20
  •   Hamza Yerlikaya    16 年前

    (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)
    
        3
  •  6
  •   Jürgen Hötzel    16 年前

    基于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) 
    

    很有趣。

        4
  •  5
  •   AlBlue RACGAMERUP    16 年前

        5
  •  3
  •   Michael Konietzka    16 年前

    字符串。字母: 在......下面具体数值为 依赖于区域设置,并将被更新 调用locale.setlocale()时。

    1. string.letters是小写加大写。

    2. JAVA Character.isLetter(char)

    Api-Doc: Character.isLetter(char) :

    一个角色被认为是一个角色 由Character.getType(ch)提供,是 下列任何一项:

    * UPPERCASE_LETTER
    * LOWERCASE_LETTER
    * TITLECASE_LETTER
    * MODIFIER_LETTER
    * OTHER_LETTER 
    

    不是所有的信都有大小写。很多 字符是字母,但两者都不是 大写,不小写,也不大写。

    如果string.letters只返回小写和大写,那么TITLECASE\u字母, ,修饰字母和其他字母字符必须忽略。

    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();
    }
    

    在虚拟机启动和 底层操作系统的字符集

    我想,在启动的JVM中,默认字符集是不能更改的。因此,string.letters的“change locale”行为不能仅用locale.setDefault(locale)实现。但更改默认区域设置无论如何都是个坏主意:

    因为更改默认区域设置可能 功能,此方法只应 如果调用者准备

        6
  •  1
  •   Bozhidar Batsov    16 年前

        7
  •  1
  •   nipra    16 年前

    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> 
    
        8
  •  1
  •   Ned Batchelder    15 年前

    与您的问题中提到的相同的结果将由以下语句给出,与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());
        }
    
    }