2012-04-13 25 views
1

私の質問は、マップとおそらくdoseqを使用して、次のreduceソリューションを書き直すにはどうすればいいですか?私は以下の解決策で多くの問題を抱えてきました。マイグレーションマップへの縮小

その解決策は、以下の問題を解決することです。具体的には、clojure-csvによって解析された2つのcsvファイルがあります。ベクトルの各ベクトルは、bene-dataおよびgic-dataと呼ぶことができます。私は、各行bene-dataの列の値を取得し、その値がgic-dataの1つの行の別の列であるかどうかを確認したいと思います。私はgic-dataに見つからないベーデータ値をベクトルに蓄積したい。私はもともと地図に蓄積しようとしましたが、それは印刷をデバッグしようとするとスタックのオーバーフローを開始しました。結局、私はこのデータを取って静的テキストと結合してレポートファイルに吐き出したいと思っています。

次のような機能:

(defn is-a-in-b 
    "This is a helper function that takes a value, a column index, and a 
    returned clojure-csv row (vector), and checks to see if that value 
    is present. Returns value or nil if not present." 
    [cmp-val col-idx csv-row] 

    (let [csv-row-val (nth csv-row col-idx nil)] 
     (if (= cmp-val csv-row-val) 
      cmp-val 
      nil))) 

(defn key-pres? 
    "Accepts a value, like an index, and output from clojure-csv, and looks 
    to see if the value is in the sequence at the index. Given clojure-csv 
    returns a vector of vectors, will loop around until and if the value 
    is found." 

    [cmp-val cmp-idx csv-data] 
    (reduce 
     (fn [ret-rc csv-row] 
      (let [temp-rc (is-a-in-b cmp-val cmp-idx csv-row)] 
       (if-not temp-rc 
        (conj ret-rc cmp-val)))) 
     [] 
     csv-data)) 


(defn test-key-inclusion 
    "Accepts csv-data param and an index, a second csv-data param and an index, 
    and searches the second csv-data instances' rows (at index) to see if 
    the first file's data is located in the second csv-data instance." 

    [csv-data1 pkey-idx1 csv-data2 pkey-idx2 lnam-idx fnam-idx] 

    (reduce 
     (fn [out-log csv-row1] 
      (let [cmp-val (nth csv-row1 pkey-idx1 nil) 
        lnam (nth csv-row1 lnam-idx nil) 
        fnam (nth csv-row1 fnam-idx) 
        temp-rc (first (key-pres? cmp-val pkey-idx2 csv-data2))] 

      (println (vector temp-rc cmp-val lnam fnam)) 
      (into out-log (vector temp-rc cmp-val lnam fnam)))) 
     [] 
     csv-data1)) 

この問題を解決するための私の試みを表しています。私は通常、repeatqを使用しない限り、結果のデータを蓄積する場所がないため、通常はdosqとmapを使用しようとしています。

答えて

2

このソリューションでは、列2のすべてをセットに1回読み込みます(つまり、レイジーではありません)。また、列1の各値に対して列2を再スキャンするよりも優れているはずです。列2が大きすぎてメモリに読み込めない場合は、必要に応じて調整します。

(defn column 
    "extract the values of a column out of a seq-of-seqs" 
    [s-o-s n] 
    (map #(nth % n) s-o-s)) 

(defn test-key-inclusion 
    "return all values in column1 that arent' in column2" 
    [column1 column2] 
    (filter (complement (into #{} column2)) column1)) 

user> (def rows1 [[1 2 3] [4 5 6] [7 8 9]]) 
#'user/rows1 

user> (def rows2 '[[a b c] [d 2 f] [g h i]]) 
#'user/rows2 

user> (test-key-inclusion (column rows1 1) (column rows2 1)) 
(5 8) 
+0

ありがとうございます。私はそれをテストしています。 – octopusgrabbus

+0

おそらく '(defnテストキーを含む[column1 column2](remove(set column2)column1))'?あなた自身を助けてください。 – Thumbnail

関連する問題