[英]How do I parse and use a table in Clojure?
我已經開始使用Clojure了,並為我為自己設置的第一個問題感到困惑。 我有一個文本文件,基本上是一個表nXm行/列。 第一行是列名,第一列是行名。 我希望能夠使用clojure和稍后的查詢表[row] [column]來解析此表並獲取該值。
a b c
1 7 8 9
2 s q r
3 2 7 1
那么,我如何在clojure中使用上表呢? 我不確定從哪里開始。 有人能讓我朝着正確的方向前進嗎?
@Hendekagon的答案是完成工作的好方法,但是我們可以從頭開始實現。 盡管可能不是最佳解決方案,但希望示例設計可以幫助您順利進行。
如果你想查詢你的結構,在Clojure中,你將會考慮地圖。 讓我們把目標看作是我們的目標:
{"1" {"a" "7", "b" "8", "c" "9"},
"2" {"a" "s", "b" "q", "c" "r"},
"3" {"a" "2", "b" "7", "c" "1"}}
在此,行名是將列名映射到表元素的鍵。 通過這種結構,我們可以使用get-in
輕松查詢表的元素。
(get-in table ["2" "b"]) ; => "q"
好的。 我們該怎么做呢?
讓我們假裝一秒鍾,我們已經在我們的文件中讀取並將其作為字符串。 然后,我們需要將其轉換為地圖。 我們的功能看起來像這樣:
(defn parse-table
[raw-table-data]
...)
第一步是提取所有重要的數據位-行名,列名和表元素。 但是,在獲取它們之前,我們需要將raw-table-data
字符串解析為更易於遍歷的結構。 我們將在換行符上分割字符串,然后使用輔助函數tokens
在空白符上標記行。
(use '[clojure.string :only [split split-lines trim]])
(defn tokens
[s]
(-> s trim (split #"\s+")))
(defn parse-table
[raw-table-data]
(let [table-data (map tokens (split-lines raw-table-data))]
...
)
table-data
看起來像這樣:
[["a", "b", "c"],
["1", "7", "8", "9"],
["2", "s", "q", "r"],
["3", "2", "7", "1"]]
這使得很容易找到好東西:
(defn parse-table
[raw-table-data]
(let [table-data (map tokens (split-lines raw-table-data))
column-names (first table-data)
row-names (map first (next table-data))
contents (map next (next table-data))]
...
)
整理好數據之后,我們只需要將它們縫合在一起即可。 一種簡單的方法是構建我們所有的行到列到元素的單獨映射,然后將它們組合起來。 我會提到這不是最有效的方法,但是很干凈。
創建一個簡單地並排粘貼兩個集合的元素的輔助函數pairs
,我們可以使用for
理解獲得一系列映射。
(defn pairs
[coll1 coll2]
(map vector coll1 coll2))
(for [[row-name row-contents] (pairs row-names contents)
[column-name element] (pairs column-names row-contents)]
{row-name {column-name element}})
這給出了一系列地圖到地圖。 我們只需要將其合並為一張大地圖,即可完成該功能。
(defn parse-table
[raw-table-data]
(let [table-data (map tokens (split-lines raw-table-data))
column-names (first table-data)
row-names (map first (next table-data))
contents (map next (next table-data))]
(apply merge-with merge
(for [[row-name row-contents] (pairs row-names contents)
[column-name element] (pairs column-names row-contents)]
{row-name {column-name element}}))))
現在,我們可以對表文件進行處理並對其進行解析。
(def table
(->
"file"
slurp
parse-table))
這讓我們達到了目標。
(println (get-in table ["2" "b"])) ; => "q"
使用https://github.com/clojure/data.csv ,您的文件將成為一系列向量,每個向量都是一行,然后可以使用如下函數解析這些行:
(defn parse-row [[a b c]]
[(Integer/parseInt a) (Double/parseDouble b) (str c)])
(請注意參數列表中的解構,這使讀取列名稱更加容易)
然后(map parse-row rows)
以獲取已分析的表
但是,另一種方法是使用Incanter ,它將把您的csv文件轉換成一個矩陣,該矩陣更易於查詢。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.