2017-11-20 6 views
-2

Ich versuche, Daten in eine Sammlung von einer Art zu speichern, aber das Programm, das ich habe, speichert alles in einer separaten Karte. Ich möchte es zu einer Karte machen.Clojure Map außerhalb Geltungsbereich

(defn readFile [] 
    (map (fn [line] (clojure.string/split line #";")) 
     (with-open [rdr (reader "C:/Users/Rohil/Desktop/textfile.txt")] 
     (doseq [[idx line] (map-indexed vector(line-seq rdr))] 

      (if(.contains line "201609") 
      (if(not(.contains line "TBA")) 
       (println(assoc table :code(nth(clojure.string/split line #";")3) :instructor(nth(clojure.string/split line #";")19))) 
      ) 
     ) 
     ) 
    ) 
    ) 
) 
) 

Jede Hilfe wird geschätzt.

+0

Was ist 'table'? Auch 'println' gibt' nil' zurück und 'assoc' ändert _not_ ** nicht an irgendwelche' (def table {}) ', die Sie vorher irgendwo eingefügt haben könnten. – cfrick

Antwort

1

Sieht aus, als ob Sie sich an clojure anpassen :-) Ich ging zum selben Prozess. Moment mal, es wird sich lohnen!

Erstens: Es ist wichtig zu wissen, dass die Map das Ergebnis der Funktion in einer neuen Sammlung speichert. Wie cfrick erwähnt, gibt printlnnil zurück und assoc ändert keine Karte.

Ich vermute, ein bisschen hier, was Sie zu tun versuchen: Sie wollen eine Sammlung von dicts haben, wo jeder dict besitzt zwei Tasten, etwa so:

[ 
    { :code 1 :instructor "blah"} 
    { :code 2 :instructor "boo" } 
] 

Sie müssen diese Werte kommen aus einer Datei, aber Sie wollen nur die Zeilen speichern, wo die Linie „201609“ enthält aber nicht „TBA“

Zunächst einige allgemeine Bemerkungen:

  • Sie wollen wahrscheinlich diese Funktion in kleinere Teile aufgeteilt. Einer könnte die Überprüfung für Zeilen sein (contains 201609 but not tba), ein anderer könnte die Datei lesen ...
  • Ich weiß, es ist der Titel Ihrer Frage, aber wahrscheinlich gibt es einen besseren Weg, als eine globale Variable zu ändern. Vielleicht könnten Sie die Funktion readFile die Tabelle zurückgeben?
  • versuchen Sie, wenn Sie Argumente an Ihre Funktion übergeben können.
  • Ich bin mir nicht sicher, was Sie mit der Linie (doseq [[... zu tun versuchen Bitte geben Sie uns mehr Kontext dort. Ich werde es ignorieren

Hier ist eine mögliche Lösung:

(ns test 
    (:require [clojure.string :as s] 
      [clojure.java.io :as io])) 

(defn line-filter [include exclude line] 
    (and (not (s/includes? line exclude)) 
     (s/includes? line include))) 

(defn process-line [line] 
    (let [line-parts (s/split line #";") 
     code (nth line-parts 3) 
     instructor (nth line-parts 19)] 
    {:code code :instructor instructor})) 

(defn read-file [file-name] 
    (s/split (slurp (io/resource file-name)) #"\n")) 

(defn parse-lines [lines] 
    (map process-line lines)) 


(defn read-file-and-parse 
    "This function will read a file, process the lines, and output a collection of maps" 
    [filename search-for exclude] 
    (parse-lines 
    (filter #(line-filter search-for exclude %) 
    (read-file filename)))) 

Sie jetzt diese Funktion wie folgt nennen könnte: (read-file-and-parse "test.txt" "201609" "TBA")

Wenn Sie das Ergebnis dieser Funktion in Ihrem table hinzufügen möchten Sie können concat verwenden. Aber auch hier wird eine neue Version Ihrer Liste (mit neuen Einträgen) zurückgegeben und die zuvor definierte nicht geändert.

Willkommen bei der funktionalen Programmierung :-)))