簡體   English   中英

如何解析和使用Clojure中的表?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM