6

データを含むテキスト ファイルを読み取る必要があるコードを書いています。テキスト ファイルの形式は次のとおりです。

name 1 4
name 2 4 5
name 3 1 9

形式でマップのベクトルを作成しようとしています[:name Sarah :weight 1 cost :4]

line-seq リーダーでファイルを読み取ろうとすると、各行がアイテムとして読み取られるため、パーティションが正しくありません。以下の repl を参照してください。

(let [file-text (line-seq (reader "C://Drugs/myproject/src/myproject/data.txt"))
                       new-test-items (vec (map #(apply struct item %) (partition 3 file-text)))]
     (println file-text)   
     (println new-test-items))


(sarah 1 1 jason 4 5 nila 3 2  jonas 5 6 judy 8 15 denny 9 14 lis 2 2  )
[{:name sarah 1 1, :weight jason 4 5, :value nila 3 2 } {:name jonas 5 6, :weight judy 8 15, :value denny 9 14}]

次に、パーティションを 1 つ取得しようとしましたが、それでも構造が正しくありません。

=> (let [file-text (line-seq (reader "C://Drugs/myproject/src/myproject/data.txt"))
                                new-test-items (vec (map #(apply struct item %) (partition 1 file-text)))]
              (println file-text)   
              (println new-test-items))
(sarah 1 1 jason 4 5 nila 3 2  jonas 5 6 judy 8 15 denny 9 14 lis 2 2  )
[{:name sarah 1 1, :weight nil, :value nil} {:name jason 4 5, :weight nil, :value nil} {:name nila 3 2 , :weight nil, :value nil} {:name jonas 5 6, :weight nil, :value nil} {:name judy 8 15, :weight nil, :value nil} {:name denny 9 14, :weight nil, :value nil} {:name lis 2 2, :weight nil, :value nil} {:name  , :weight nil, :value nil}]
nil

次に、ファイルを丸呑みしようとしましたが、それはさらに悪いことです:

=> (let [slurp-input (slurp "C://Drugs/myproject/src/myproject/data.txt")
            part-items (partition 3 slurp-input)
            mapping (vec (map #(apply struct item %) part-items))]
            (println slurp-input)
            (println part-items)
            (println mapping))
sarah 1 1
jason 4 5
nila 3 2 
jonas 5 6
judy 8 15
denny 9 14
lis 2 2

((s a r) (a h  ) (1   1) (

助けてください!これは Java で行うのはとても簡単なことのように思えますが、Clojure で私を殺しています。

4

2 に答える 2

7

それを一連の行に分割します。

(line-seq (reader "/tmp/data"))

それぞれを一連の単語に分割します

(map #(split % #" ") data)

1 つのデータのベクトルを取り、それを正しいキーを持つマップに変換する関数を作成します

(fn [[name weight cost]] 
   (hash-map :name name 
             :weight (Integer/parseInt weight) 
             :cost (Integer/parseInt cost))) 

次に、それらを入れ子に戻します

(map (fn [[name weight cost]] 
       (hash-map :name name 
                 :weight (Integer/parseInt weight) 
                 :cost (Integer/parseInt cost))) 
     (map #(split % #" ") (line-seq (reader "/tmp/data"))))

({:weight 1, :name "name", :cost 4} 
 {:weight 2, :name "name", :cost 4} 
 {:weight 3, :name "name", :cost 1})

を使用して、これをよりコンパクトにすることもできますzip-map

于 2012-07-15T19:05:34.613 に答える
3

中間結果をテストせずに、すべてを 1 か所で実行しようとしています。代わりに、Clojure はタスクをいくつかのサブタスクに分解することを推奨しています。これにより、コードがより柔軟テストしやすくなります。これがあなたのタスクのコードです(ファイル内のレコードは人々を説明していると思います):

(defn read-lines [filename]
  (with-open [rdr (clojure.java.io/reader filename)]
    (doall (line-seq rdr))))

(defn make-person [s]
  (reduce conj (map hash-map [:name :weight :value] (.split s " "))))

(map make-person (read-lines "/path/to/file"))
于 2012-07-15T20:36:55.167 に答える