2012-07-15 37 views
6

Tôi đang viết một đoạn mã cần đọc trong một tệp văn bản có dữ liệu. Tệp văn bản có định dạng:Cách đọc tệp có dữ liệu thử nghiệm bằng Clojure?

name 1 4 
name 2 4 5 
name 3 1 9 

Tôi đang cố gắng tạo một vectơ bản đồ ở dạng [:name Sarah :weight 1 cost :4].

Khi tôi thử đọc tệp bằng trình đọc dòng-seq, nó đọc từng dòng dưới dạng mục nên phân vùng không chính xác. Xem thay thế bên dưới:

(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}] 

Sau đó tôi đã cố gắng chỉ mất 1 phân vùng, nhưng cấu trúc vẫn không đúng.

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

Tiếp theo, tôi đã cố gắng để húp tập tin, nhưng đó là tồi tệ hơn:

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

Xin giúp! Điều này có vẻ như một điều dễ dàng như vậy để làm trong Java, nhưng đang giết tôi trong Clojure.

Trả lời

6

chia nó thành một chuỗi các dòng:

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

chia mỗi người trong số chúng thành một chuỗi các từ

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

làm một chức năng mà phải mất một vector của một dữ liệu và biến nó thành một bản đồ với các phím chính xác

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

sau đó lồng chúng lại với nhau

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

bạn cũng có thể làm cho điều này nhỏ gọn hơn bằng cách sử dụng zip-map

+1

vì điều này là lười, bạn nên nhớ đóng tệp khi bạn sẽ không đọc thêm dữ liệu nào nữa. (Tôi thường thấy các trình tự tự gói của mình trong một trình đọc lười biếng gần như trống rỗng. –

+0

tách ra từ clojure.string và trình đọc đến từ clojure.java.io –

+0

Arthur cảm ơn bạn rất nhiều! Tôi đã mất đi điều này. giải pháp, nhưng tôi nhận được lỗi sau. => (map (fn [[name weight cost]] (hash-map: name name : weight (Integer/parseInt weight) : cost (Integer/parseInt cost)))) (bản đồ # (chia% # "") (dòng-seq (trình đọc "C: //Drugs/myproject/src/myproject/data.txt"))))) CompilerException java.lang.RuntimeException: Không thể phân giải biểu tượng : phân chia trong bối cảnh này, biên dịch: (NO_SOURCE_PATH: 5) – user1525748

3

Bạn đang cố gắng làm tất cả mọi thứ ở một nơi mà không cần kiểm tra kết quả trung gian. Thay vào đó Clojure khuyên bạn nên phân chia nhiệm vụ thành một số nhiệm vụ phụ - điều này làm cho mã nhiều hơn linh hoạtcó thể kiểm tra. Đây là mã cho công việc của bạn (Tôi giả sử các hồ sơ trong tệp mô tả mọi người):

(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")) 
Các vấn đề liên quan