2012-04-13 12 views
1

Meine Frage ist, wie kann ich die folgende Lösung reduzieren mit Karte und wahrscheinlich doseq schreiben? Ich habe eine Menge Probleme mit der folgenden Lösung.Migrieren reduzieren auf Karte

Diese Lösung soll das folgende Problem lösen. Insbesondere habe ich zwei csv-Dateien, die von clojure-csv analysiert wurden. Jeder Vektor von Vektoren könnte Bene-Daten und Gic-Daten genannt werden. Ich möchte den Wert in einer Spalte in jeder Zeile bene-Daten nehmen und sehen, ob dieser Wert eine andere Spalte in einer Zeile in GIC-Daten ist. Ich möchte diese bene-Datenwerte, die nicht in gic-Daten gefunden werden, in einem Vektor ansammeln. Ich versuchte ursprünglich, in einer Karte zu akkumulieren, und das begann den Stapelüberlauf beim Versuch, den Druck zu debuggen. Schließlich möchte ich diese Daten nehmen, mit etwas statischem Text kombinieren und in eine Berichtsdatei spucken.

Die folgenden Funktionen:

(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)) 

repräsentieren meinen Versuch, dieses Problem zu lösen. Ich laufe normalerweise in eine Wand und versuche, doseq und map zu verwenden, weil ich nirgends die resultierenden Daten ansammeln kann, es sei denn, ich benutze loop recur.

Antwort

2

Diese Lösung liest alle der Spalte 2 in einem Satz einmal (so ist es nicht faul) für die Leichtigkeit des Schreibens. Es sollte auch eine bessere Leistung als das erneute Scannen von Spalte 2 für jeden Wert von Spalte 1 erbringen. Passen Sie dies bei Bedarf an, wenn Spalte 2 zu groß ist, um im Speicher gelesen zu werden.

(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

Vielen Dank. Ich teste es. – octopusgrabbus

+0

Vielleicht '(defn test-key-inklusion [column1 column2] (remove (set column2) column1))? Bedienen Sie sich. – Thumbnail

Verwandte Themen