2010-04-05 6 views
11

अजगर में, मैं यह कर सकता हूँ:मैं जावा/क्लोजर में सभी अक्षरों का सेट कैसे प्राप्त करूं?

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

वहाँ Clojure में इसी तरह कुछ करना (अलग नकल से और कहीं ऊपर पात्रों चिपकाने) करने के लिए कोई तरीका है? मैंने क्लोजर मानक पुस्तकालय और जावा मानक पुस्तकालय दोनों को देखा और इसे नहीं मिला।

+6

मैं पाइथन परिणाम पूरी तरह से गलत मानता हूं। Ä, é या ß के बारे में क्या? –

+4

मुझे लगता है कि अगर मैं पाइथन के 'string.letters' पर प्रलेखन देता हूं तो यह मदद करेगा: http://docs.python.org/library/string.html#string।अक्षरों यह ASCII- आधारित है, इसलिए लौटाया गया मूल्य सिस्टम-निर्भर है। –

+4

"यह मूल्य सिस्टम-निर्भर" कैसे है "यह ASCII- आधारित" से पालन करता है? ASCII अच्छी तरह से परिभाषित है और प्रत्येक प्रणाली पर बिल्कुल वही है। तो अगर यह वास्तव में ASCII- आधारित था, तो परिणाम हमेशा वही होगा। "ASCII" किसी भी 8-बिट वर्ण एन्कोडिंग का पर्याय नहीं है। –

उत्तर

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

इसे "यूएस-एएससीआईआईआई" के साथ कॉल करें और आपको वांछित परिणाम मिलेगा (सिवाय इसके कि अपरकेस अक्षरों को पहले आना चाहिए)। आप इसे Charset.defaultCharset() के साथ कॉल कर सकते हैं, लेकिन मुझे संदेह है कि आप संयुक्त राज्य अमेरिका में भी अधिकांश प्रणालियों पर ASCII अक्षरों से कहीं अधिक प्राप्त करेंगे।

चेतावनी: केवल मूल बहुभाषी विमान को मानता है। पूरक विमानों में विस्तार करना बहुत कठिन नहीं होगा, लेकिन इसमें बहुत अधिक समय लगेगा, और उपयोगिता संदिग्ध है।

+3

Character.isLetter (चार) uppercases और lowercases तुलना में अधिक है: एक चरित्र का कोई अक्षर होना अगर इसकी सामान्य श्रेणी प्रकार, Character.getType (ch) द्वारा प्रदान की, इनमें से कोई भी माना जाता है: * UPPERCASE_LETTER * LOWERCASE_LETTER * TITLECASE_LETTER * MODIFIER_LETTER * OTHER_LETTER सभी अक्षरों में कोई मामला नहीं है। कई पात्र पत्र हैं लेकिन न तो अपरकेस हैं और न ही लोअरकेस और न ही शीर्षक के हैं। –

+0

बस एक छोटी सी चाल है: आप 'for c' स्थिति को इस तरह से लिख सकते हैं (char c = 1; c> 0; C++) '। – Elist

1

मुझे यकीन है कि पत्र मानक पुस्तकालय में उपलब्ध नहीं हैं, इसलिए आप शायद मैन्युअल दृष्टिकोण के साथ छोड़ दिए गए हैं।

5

नहीं, क्योंकि यह सिर्फ पूर्ण सेट के बजाय ASCII अक्षरों को प्रिंट कर रहा है। बेशक, 26 लोअर केस और ऊपरी केस अक्षरों को लूप के लिए दो का उपयोग करके मुद्रित करना मुश्किल है लेकिन तथ्य यह है कि पहले 127 कोड बिंदुओं के बाहर कई और "अक्षर" हैं। चरित्र पर जावा का "isLetter" fn इन और कई अन्य लोगों के लिए सच होगा।

+0

यह एक उत्कृष्ट बिंदु है, लेकिन मैं अभी यूनिकोड के बारे में बहुत चिंतित नहीं हूं। उस ने कहा, मुझे लगता है कि मैं मैन्युअल दृष्टिकोण का उपयोग कर सकता हूं। ऐसा नहीं है कि वर्णमाला जल्द ही बदलने का खतरा है। :-) –

+1

@ जेसन: पत्र "राजधानी ß" ने 2008 में यूनिकोड मानक में प्रवेश किया है! और यह लैटिन वर्णमाला से एक पत्र है! (माना जाता है, यह बहुत ही कम इस्तेमाल होता है, लेकिन फिर भी: परिवर्तन से भी अक्षर सुरक्षित नहीं हैं)। –

1

ही परिणाम अपने प्रश्न में उल्लेख किया है के रूप में निम्नलिखित बयान है कि मैन्युअल रूप से अजगर समाधान के विपरीत उत्पन्न होने से दी जाएगी:

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

} 
3

string.letters: तार लोअरकेस और अपरकेस नीचे वर्णित के संयोजन। विशिष्ट मान लोकेल-निर्भर है, और 0aleअपडेट किया जाएगा जब locale.setlocale() को कॉल किया जाता है।

मैंने माइकल बोर्गवर्ड से जवाब संशोधित किया।

  1. string.letters uppercases के बाद lowercases है: मेरी कार्यान्वयन में वहाँ दो सूचियों lowerCases और दो कारणों के लिए upperCases हैं।

  2. जावा Character.isLetter(char) से अधिक सिर्फ uppercases और lowercases, तो Character.isLetter (चार) के उपयोग के बहुत परिणाम के लिए Api-Doc: Character.isLetter(char) से उदाहरण "windows-1252"

के लिए, कुछ वर्णसेट के तहत वापस आ जाएगी है:

एक चरित्र है, तो अपने सामान्य श्रेणी प्रकार, Character.getType (ch) द्वारा प्रदान की, निम्न में से किसी भी है एक पत्र माना जाता है:

* UPPERCASE_LETTER 
* LOWERCASE_LETTER 
* TITLECASE_LETTER 
* MODIFIER_LETTER 
* OTHER_LETTER 

सभी अक्षरों में कोई मामला नहीं है।कई वर्ण पत्र हैं लेकिन न तो अपरकेस और न ही लोअरकेस और न ही शीर्षक के हैं।

तो अगर string.letters केवल lowercases और uppercases लौटना चाहिए, 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 से:

डिफ़ॉल्ट चारसेट आभासी मशीन स्टार्टअप के दौरान निर्धारित किया जाता है और आम तौर पर स्थान और अंतर्निहित ऑपरेटिंग प्रणाली के चारसेट पर निर्भर करता है।

मुझे लगता है कि डिफ़ॉल्ट वर्णसेट प्रारंभिक जेवीएम में बदला नहीं जा सकता है। इसलिए string.letters के "लोकेल बदलें" व्यवहार को Locale.setDefault (लोकेल) के साथ वास्तविकता नहीं दी जा सकती है। लेकिन डिफ़ॉल्ट स्थान बदलने वैसे भी एक बुरा विचार है:

के बाद से सामान्य स्थान कार्यक्षमता के कई अलग अलग क्षेत्रों को प्रभावित कर सकता बदलते, इस विधि को केवल तभी फोन करने वाले reinitialize करने के लिए तैयार किया जाता है इस्तेमाल किया जा चाहिए वातावरण के प्रति संवेदनशील कोड उसी जावा वर्चुअल मशीन के भीतर चल रहा है।

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) 
+2

+1 किसी अज्ञात फ़ंक्शन में कॉल को चार में लपेटने की आवश्यकता नहीं है, '(नक्शा चार (कॉन्सट (रेंज 65 9 1) (रेंज 9 7 123)))' ठीक काम करेगा। – Jonas

6

माइकल्स जरूरी जावा समाधान के आधार पर, यह एक मुहावरेदार (आलसी दृश्यों) 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) 

के बीच performace तुलना काफी रोचक है ।

+1

बेवकूफ आलसी seq fns शायद ही आलसी-सीक का उपयोग करें: आलसी-सीईसी निम्न स्तर है। आपके कोड का मूल बेहतर लिखा गया है: (- >> (रेंज 0 (इंट कैरेक्टर/MAX_VALUE)) (नक्शा चार) (फ़िल्टर # (और (.canEncode ce%) (कैरेक्टर/isLetter%))) http देखें: //gist.github.com/357407। एक और बात: और .. somewaht विरासत हैं इसलिए उनका उपयोग न करें। – cgrand

+0

धन्यवाद! "।" और ".." विरासत क्यों माना जाता है? कोई संसाधन? –

+1

-> है एक बेहतर .. चूंकि आप एफएन और विधियों (.method नोटेशन में) मिश्रण करते हैं, इसलिए .. आपको एक डॉट प्रति विधि कॉल को सहेजने के अलावा कोई रूचि नहीं है (और जब आप टाइप-संकेत करते हैं तो उन्हें स्पॉट करने में कम आसान बनाते हैं)। (और। विधि obj) विधि को फ़ंक्शन स्थिति में डालकर अधिक लज्जास्पद है। इसी प्रकार फू को (नया फू) पसंद करें। शक्कर के रूप (.foo, foo। और foo/BAR) को आज़माएं और आप देखेंगे कि वे हैं उपयोग करने के लिए बहुत अच्छा (और बाद में आसान कारक बनाने की अनुमति दें) – cgrand

1

यदि आपको कोड बिंदु सीमाएं याद नहीं हैं। ब्रूट फोर्स रास्ता :-पी:

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>