2017-01-03 5 views
0
(defn num-as-words [n] 
     (let [words '("zero" "one" "two" "three" "four" 
          "five" "six" "seven" "eight" "nine")] 
      (clojure.string/join "-" 
           (map (fn [x] (nth words (Integer. (re-find #"\d" (str x))))) (str n))))) 

この関数は、num-as-wordsと呼ばれ、整数を取り、完全な単語として表示するあなたはそれを返すでしょう(123)(1,2,3)。Clojureで完全な言葉で(負ではない)整数を出力する関数を書く

私はマップを使って行っていますが、別の方法があるかどうか疑問に思っていましたか?私はまた、clojure.string/joinよりも言葉をつなぐ別の方法があるのだろうかと疑問に思っていました。私は最初にinterposeを使っていましたが、出力していた方法が好きではありませんでした( "one" - "two " "-" "三")。

ご協力いただきますようお願い申し上げます。ありがとうございます。

答えて

3

私はこのようにそれを実装したい:

(defn num-as-words [n] 
    (let [words ["zero" "one" "two" "three" "four" "five" "six" "seven" "eight" "nine"]] 
    (->> (str n) 
     (map #(Character/getNumericValue %)) 
     (map words) 
     (clojure.string/join "-")))) 
  • 実装を簡素化しますベクターを用いて。
  • 数字ストリングを正規表現で分割する代わりに、シーケンスとして扱うことができます。この場合、charを整数に変換するにはCharactor/getNumericValueを使用する必要があります。
  • ->>マクロを使用できます。
  • clojure.string/joinを使用してください。
  • interposeはレイジーシーケンスを返します。だからそれは("one" "-" "two"...)のように返されます。結果にapply str(apply str (interpose ...))を文字列に変換する必要があります。

あなたが負の数を処理したい場合、あなたはこのようなコードを変更することができます。

(defn num-as-words [n] 
    (if (< n 0) 
    (str "-" (num-as-words (- n))) 
    (let [words ["zero" "one" "two" "three" "four" "five" "six" "seven" "eight" "nine"]] 
     (->> (str n) 
      (map #(Character/getNumericValue %)) 
      (map words) 
      (clojure.string/join "-"))))) 

これは前に-を付加します。あなただけのエラーをスローする場合は、前提条件を使用することができます。

(defn num-as-words [n] 
    {:pre [(<= 0 n)]} 
    (let [words ["zero" "one" "two" "three" "four" "five" "six" "seven" "eight" "nine"]] 
    ... 

それは負の数を受信したときにこれがAssertionErrorがスローされます。

+0

ありがとうございます。 の負の数値を入力した場合にエラー処理がどうなるか考えていますか? – danfs

+0

@bigd答えを更新します。 – ntalbs

+0

私は '(map#(nth words%))'をより単純な同等の '(map words) 'に置き換える自由を取ってきました。これはClojure関数ではなく、Java静的メソッドである 'Character/getNumericValue'では機能しません。 – Thumbnail

5
user=> (clojure.pprint/cl-format  ; formatted printing 
     nil       ; ... to a string 
     "~{~R~^-~}"     ; format (see below) 
     (map       ; map over characters 
      (fn [x] (Integer. (str x))) ; convert char to integer 
      (str 123)))     ; convert number to string 
"one-two-three" 
  • まず、私たちは一例で、ここで"123"としてハードコーディングされ、入力された番号を取り、mapのおかげで、文字列としてそれを強要し、結果の文字列の文字を反復処理。各文字について、その文字を含む文字列を作成し、それをIntegerとして解析します。したがって、我々は数字のリストを得る。

    もっと正確には、(fn [x] ...)は1つの引数を取る関数です。文字を繰り返し処理するので、代わりにcharとする必要があります(申し訳ありません)。 (str x)を評価すると、1つの文字を含む文字列、つまりxが得られます。たとえば、文字が\2の場合、結果の文字列は"2"です。 (Integer. string)フォーム(ドットに注意!)は、文字列を整数として解析するIntegerクラスのコンストラクタを呼び出します。私たちの例を続行するには、(Integer. "2")は、我々は(false引数で要求されるように)新鮮な文字列に数字のリストを印刷するcl-formatを使用して整数2

  • をもたらすであろう。これを行うために、次の形式を指定します。

  • ~{...~}は、リストを繰り返し処理し、各要素の中括弧内の書式を実行します。

  • ~R(等、1 => 1)英語の単語として番号を印刷
  • ない残りの引数が存在しない場合~{...~}製反復をエスケープ~^。したがって、最後の桁を印刷すると、~^に続く部分は印刷されません。
  • ~^に続くものは、単に文字-です。これは文字列を区切るために使用されますが、ループのすべての繰り返しに対してダッシュを表示しないように注意しなければなりません。そうでない場合、結果の文字列はダッシュで終了します。

文字が整数として解析できない場合、関数はエラーを報告します。文字列に変換する前に、入力が実際に正の整数であることを最初に確認したい場合があります。

+1

cl-format!すべての中で最も暗い魔法。 : –

+0

(fn [x](整数。(str x))) (str 123))) このセクションの内容を詳しく説明してもらえませんか、私はそれに問題があります – danfs

+0

@danfs詳細を編集 – coredump

関連する問題