2012-01-07 10 views
2

マップ操作から返された(遅延した)シーケンスを別のマップ操作に渡して、要素を参照できるようにしようとしています最初のシーケンスで。コードはテキストファイル(行/列形式)からいくつかのサッカーフィクスチャを解析し、それをクリーンアップしてからマップを返します。ここでClojure例外を防止する方法:clojure.lang.LazySeqはclojure.lang.IFnにキャストできません

は、コードは次のとおりです。

(ns fixtures.test.lazytest 
    (:require [clojure.string :as str]) 
    (:use [clojure.test])) 

(defn- column-map 
    "Produce map with column labels given raw data, return nil if not enough columns" 
    [cols] 
    (let [trimmed-cols (map str/trim cols) 
     column-names {0 :fixture-type, 1 :division, 2 :home-team, 4 :away-team}] 
    (if (> (count cols) (apply max (keys column-names))) 
     (zipmap (vals column-names) (map trimmed-cols (keys column-names))) 
     nil))) 

(deftest test-mapping 
    (let [cols '["L" " Premier " " Chelsea " "v" "\tArsenal "] 
     fixture (column-map cols)] 
    (is (= "Arsenal" (fixture :away-team))) 
    (is (= "Chelsea" (fixture :home-team))) 
    (is (= "Premier" (fixture :division))) 
    (is (= "L" (fixture :fixture-type))) 
) 
) 

(run-tests 'fixtures.test.lazytest) 

私が取っているアプローチは次のとおりです。

  1. は、zipmapを使用して
  2. (先頭/末尾のスペースを削除)列データのベクトルをクリーンアップ列名キーワードと列データの対応する要素を組み合わせます(すべての列が使用されているわけではありません)。
私が思うにclojure.lang.LazySeqがclojure.lang.IFn

にキャストすることはできません。10

問題が

とjava.lang.ClassCastExceptionが発生しzipmapにトリミング-colsのを使用して、あります私はなぜこれが起こっているのか知っています... trimmed-colsはLazySeqです.zipmapから呼び出されたマップは、最初の引数として非関数を受け取ることに反対しています。

trimmed-cols (vec (map str/trim cols)) 

しかし、これは、「最良の」オプションのように感じていない:私はのにを聞かせて変更することができます。この問題を解決するには

。だから、

  1. は別のマップへの「機能」の引数としてマップ操作の結果を使用するための良い一般的な解決策はありますか?
  2. ベクトル要素のすべてが使用されていない生の値データのベクトルから{:value}ペアのマップを導き出すためのより良いアプローチがありますか?

私はあなたが後にしているものを全くわからない

答えて

3

(私は。どこかでこれを行うための一般的に受け入れられている方法がなければならない慣用ソリューションを求めるが、想像することを躊躇し)、私あなたのコードが失敗する理由を見ることができます - あなたが言ったように、trimmed-colsは関数ではありません。これは単純に機能しませんか?

スキップする必要がある列に:_dummyのキーを使用しています。 ベクターで好きな数だけ使用することができます:zipmapは、それらを1つにマージします。これは、dissocによって削除されます。

(defn- column-map 
    "Produce map with column labels given raw data, return nil if not enough columns" 
    [cols] 
    (let [trimmed-cols (map str/trim cols) 
     column-names [:fixture-type :division :home-team :_dummy :away-team]] 
    (if (>= (count cols) (count column-names)) 
     (dissoc (zipmap column-names trimmed-cols) :_dummy) 
     nil))) 

(column-map ["L" " Premier " " Chelsea " "v" "\tArsenal "]) 
; => {:away-team "Arsenal", :home-team "Chelsea", :division "Premier", :fixture-type "L"} 
+0

ニース...私はあなたのソリューションがzipmapコールを簡素化し、キーワード名は何が起こっているのか(ER)、それを明確にするので、これは私の質問の後半部分をどのように対処するかが好きです。最初の部分では、マップ結果を(vec ...)を持つベクタに変換すると、関数としてアクセスできます(小さなリストサイズの場合はOKです)。 –

関連する問題