2012-07-15 5 views
6

मैं कोड का एक टुकड़ा लिख ​​रहा हूं जिसे डेटा फ़ाइल में पढ़ने की आवश्यकता है जिसमें डेटा है। पाठ फ़ाइल स्वरूप में है:क्लोजर के साथ परीक्षण डेटा वाले फ़ाइल को कैसे पढ़ा जाए?

name 1 4 
name 2 4 5 
name 3 1 9 

मैं प्रपत्र [:name Sarah :weight 1 cost :4] में एक मानचित्र का एक वेक्टर बनाने के लिए कोशिश कर रहा हूँ।

जब मैं लाइन seq रीडर के साथ में फ़ाइल को पढ़ने की कोशिश, यह एक आइटम के रूप में प्रत्येक पंक्ति पढ़ता है तो विभाजन सही नहीं है। नीचे प्रतिलिपि देखें:

(let [file-text (line-seq (reader "C://Drugs/myproject/src/myproject/data.txt")) 
         new-test-items (vec (map #(apply struct item %) (partition 3 file-text)))] 
    (println file-text) 
    (println new-test-items)) 


(sarah 1 1 jason 4 5 nila 3 2 jonas 5 6 judy 8 15 denny 9 14 lis 2 2 ) 
[{:name sarah 1 1, :weight jason 4 5, :value nila 3 2 } {:name jonas 5 6, :weight judy 8 15, :value denny 9 14}] 

मैंने फिर केवल 1 विभाजन लेने की कोशिश की, लेकिन फिर भी संरचना सही नहीं है।

=> (let [file-text (line-seq (reader "C://Drugs/myproject/src/myproject/data.txt")) 
           new-test-items (vec (map #(apply struct item %) (partition 1 file-text)))] 
       (println file-text) 
       (println new-test-items)) 
(sarah 1 1 jason 4 5 nila 3 2 jonas 5 6 judy 8 15 denny 9 14 lis 2 2 ) 
[{:name sarah 1 1, :weight nil, :value nil} {:name jason 4 5, :weight nil, :value nil} {:name nila 3 2 , :weight nil, :value nil} {:name jonas 5 6, :weight nil, :value nil} {:name judy 8 15, :weight nil, :value nil} {:name denny 9 14, :weight nil, :value nil} {:name lis 2 2, :weight nil, :value nil} {:name , :weight nil, :value nil}] 
nil 

अगला मैं फ़ाइल slurp करने की कोशिश की, लेकिन वह भी बदतर है:

=> (let [slurp-input (slurp "C://Drugs/myproject/src/myproject/data.txt") 
      part-items (partition 3 slurp-input) 
      mapping (vec (map #(apply struct item %) part-items))] 
      (println slurp-input) 
      (println part-items) 
      (println mapping)) 
sarah 1 1 
jason 4 5 
nila 3 2 
jonas 5 6 
judy 8 15 
denny 9 14 
lis 2 2 

((s a r) (a h ) (1 1) (

कृपया मदद! ऐसा लगता है कि जावा में ऐसा करना आसान है, लेकिन क्लोजर में मुझे मार रहा है।

उत्तर

6

लाइनों के अनुक्रम में इसे विभाजित: उनमें से प्रत्येक

(line-seq (reader "/tmp/data")) 

विभाजन शब्द के अनुक्रम में रखता

(map #(split % #" ") data) 

एक समारोह है कि एक डेटा का एक वेक्टर लेता है और यह एक में बदल जाता है बनाने के सही कुंजी के साथ नक्शा

(fn [[name weight cost]] 
    (hash-map :name name 
      :weight (Integer/parseInt weight) 
      :cost (Integer/parseInt cost))) 

तो घोंसला उन्हें वापस एक साथ

(map (fn [[name weight cost]] 
     (hash-map :name name 
       :weight (Integer/parseInt weight) 
       :cost (Integer/parseInt cost))) 
    (map #(split % #" ") (line-seq (reader "/tmp/data")))) 

({:weight 1, :name "name", :cost 4} 
{:weight 2, :name "name", :cost 4} 
{:weight 3, :name "name", :cost 1}) 

आप भी zip-map

+1

क्योंकि इस आलसी है, यह आप पर निर्भर फ़ाइल जब आप इसे से किसी भी अधिक डेटा को पढ़ने के लिए नहीं जा रहे हैं बंद करने के लिए याद करने के लिए। (मैं अक्सर एक करीबी जब खाली आलसी रीडर में मेरी आत्म रैपिंग दृश्यों पाते हैं। –

+0

विभाजन clojure.string से आता है और पाठक clojure.java.io –

+0

से आता आर्थर बहुत बहुत धन्यवाद! मैं इस पर खो गया था। मैंने कोशिश की अपने समाधान, लेकिन मुझे निम्न त्रुटि मिलती है। => (मानचित्र (एफएन [[नाम वजन लागत]] (हैश-मानचित्र: नाम का नाम : वजन (पूर्णांक/पारसी वजन) : लागत (पूर्णांक/पारस्परिक लागत)) (मानचित्र # (विभाजन% # "") (लाइन-सेक (पाठक "C: //Drugs/myproject/src/myproject/data.txt")))) CompilerException java.lang.RuntimeException: प्रतीक नहीं लगाया जा सका : इस संदर्भ में विभाजन, संकलन: (NO_SOURCE_PATH: 5)। – user1525748

3

का उपयोग कर आप मध्यवर्ती परिणाम परीक्षण के बिना एक ही स्थान पर सब कुछ करने की कोशिश कर रहे द्वारा इस अधिक कॉम्पैक्ट बना सकते हैं। इसके बजाय Clojure उप-कार्य के एक नंबर में कार्य विघटित करने की सिफारिश - यह बहुत अधिक लचीला और परीक्षण योग्य कोड बनाता है। यहाँ अपने कार्य के लिए कोड है (मुझे लगता है फ़ाइल में रिकॉर्ड लोगों का वर्णन):

(defn read-lines [filename] 
    (with-open [rdr (clojure.java.io/reader filename)] 
    (doall (line-seq rdr)))) 

(defn make-person [s] 
    (reduce conj (map hash-map [:name :weight :value] (.split s " ")))) 

(map make-person (read-lines "/path/to/file")) 
संबंधित मुद्दे