1

私の質問は、map とおそらく doseq を使用して、次の reduce ソリューションをどのように書き直すことができるかということです。私は次の解決策で多くの問題を抱えています。

その解決策は、次の問題を解決することです。具体的には、clojure-csv によって解析された 2 つの csv ファイルがあります。ベクトルの各ベクトルは、bene-data および gic-data と呼ぶことができます。各行 bene-data の列の値を取得し、その値が gic-data の 1 つの行の別の列であるかどうかを確認したいと考えています。gic-data にないこれらの bene-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))

この問題を解決するための私の試みを表しています。通常、doseq と map を使用しようとすると壁にぶつかります。なぜなら、ループ再帰を使用しない限り、結果のデータを蓄積する場所がないからです。

4

1 に答える 1

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)
于 2012-04-13T15:19:31.520 に答える