Mapからのデータの抽出

プログラミング技術  ICT技術  Javascriptによるフロントエンド開発  ウェブ技術 Clojureと関数プログラミング デジタルトランスフォーメーション

Clojureでデータ処理を行う際に、よく使うのがMapデータへのアクセスだ。たとえばpostgresqlデータベース等の出力あるいはCSVのデータのマップとして以下のようなものがあるとする。

(def output-text [{:id 1 :text "aaa" :tag true}
                 { :id 2 :text "bbb" :tag false}
                 { :id 3 :text "ccc" :tag true}
                 { :id 4 :text "ddd" :tag true}
                 { :id 5 :text "eee" :tag false}])

この中から、任意の:textのデータを抽出したい時は

(defn output-data [n]
  (->> output-text
     (filter #(= (:text %) n))
      first))

とすると

(output-data "ccc") 
->  {:id 3 :text "ccc" :tag true}

のように抽出できる。「=」関数の代わりに「re-find」関数を使うと、以下のように簡単な全文検索のようなことも出来る。

(defn search-data [n]
       (filter #(re-find  (re-pattern n) (:text %)) output-text))

ここで、rdf storeの出力のようなもう少し複雑にネストしたmap構造(例えば以下のようなxmlから生成されたもの)の場合は

<root>
  <records>
    <record id="1">record01</record>
    <record id="2">record02</record>
  </records>
  <record id="3">record03</record>
</root>

clojure.data.zipを使って以下のようにleiningenのdependencyを設定して

[org.clojure/data.zip "1.0.0"]

以下のような形でデータを抽出する。

(use 'clojure.data.zip.xml)
(require ['clojure.xml :as 'xml])
(require ['clojure.zip :as 'zip])

(xml-> (zip/xml-zip (xml/parse "in.xml")) :records :record text)
; -> ("record01" "record02")

(xml-> (zip/xml-zip (xml/parse "in.xml")) :record text)
; -> ("record03")

(xml-> (zip/xml-zip (xml/parse "in.xml")) :record (attr :id))
; -> ("3")

複雑な構造のデータの場合は、SAPRQL等のクエリで直接DBからAPI経由で加工済みのデータを取る方がより簡易にできると思う。

コメント

  1. […] Mapからのデータの抽出 […]

タイトルとURLをコピーしました