【问题标题】:Is there a better way to access nested maps and vectors in Clojure?有没有更好的方法来访问 Clojure 中的嵌套映射和向量?
【发布时间】:2012-12-07 04:52:25
【问题描述】:

我正在从here on freebase 获取一些 json(注意,您只能请求几次而不使用 &key=your-key)。

我想将响应转换成类似这样的内容:

    ({:case "Roe v. Wade", :plaintiffs ("Norma McCorvey"), :defendants ("Henry Wade"), :court "Supreme Court of the United States", :subjects ("Abortion" "Privacy"), :article "http://wp/en/68493"} ...)

这是我在使用 clojure.data.json/read-string 后想出的代码:

    (defn extract-data [case]
      {:case (case "name")
       :plaintiffs (flatten (map #(get % "parties") (filter (fn [p] (some #(= (% "id") "/en/plaintiff") (p "role")))
                                                           (case "/law/legal_case/parties"))))
       :defendants (flatten (map #(get % "parties") (filter (fn [p] (some #(= (% "id") "/en/defendant") (p "role")))
                                                           (case "/law/legal_case/parties"))))
       :court (get-in case ["court" 0 "name"])
       :subjects (map #(% "name") (case "subject"))
       :article (get-in case ["/common/topic/article" 0 "source_uri" 0])})

    (def response (-> query-uri
                       java.net.URL.
                       slurp
                       json/read-str))
    (def case-data (map extract-data (response "result")))

提取数据似乎过于复杂,有没有更好的方法来做到这一点?这是可以使用 core.logic 的情况吗?如果有,怎么做?

【问题讨论】:

    标签: clojure clojure-core.logic


    【解决方案1】:

    您可能会查看不同的查询系统(zip-filters、core.logic、datomic 的集合数据日志等)。或者推出您自己的临时广告:

    (defn select [x path]
      (if-let [[p & ps] (seq path)]
        (if (fn? p)
          (mapcat #(select % ps) (filter p x))
          (recur (get x p) ps))
        x))
    
    (def mapping
      {:case ["name"]
       :plaintiffs ["/law/legal_case/parties"
                    #(= (get-in % ["role" 0 "id" 0]) "/en/plaintiff")
                    "parties"]
       :defendants ["/law/legal_case/parties"
                    #(= (get-in % ["role" 0 "id" 0]) "/en/defendant")
                    "parties"]
       :court ["court" 0 "name" 0]
       :subjects ["subject" (constantly true) "name"]
       :article ["/common/topic/article" 0 "source_uri" 0]})
    
    (defn extract-data [x mapping]
      (into {}
        (for [[k path] mapping]
          [k (if (some fn? path) (select x path) (get-in x path))])))
    

    然后 (map #(extract-data % mapping) results) 应该可以解决问题

    => (extract-data (first result) mapping)
    {:case "Roe v. Wade", :plaintiffs ("Norma McCorvey"), :defendants ("Henry Wade"), :court "Supreme Court of the United States", :subjects ("Abortion" "Privacy"), :article "http//wp/en/68493"}
    

    这种类型的代码(查询解释器)可能很脆弱,所以一定要有一个测试套件。

    【讨论】:

      【解决方案2】:

      Specter 可以帮忙。

      (ns stackoverflow-answer.core
        (:require [com.rpl.specter :refer :all]))
      
      ; your example data
      (def case {"name" "Roe v. Wade"
                 "/law/legal_case/parties" [{"role" [{"id" "/en/plaintiff"}]
                                             "parties" ["Norma McCorvey"]}
                                            {"role" [{"id" "/en/defendant"}]
                                             "parties" ["Henry Wade"]}]
                 "court" [{"name" "Supreme Court of the United States"}]
                 "subject" [{"name" "Abortion"}
                            {"name" "Privacy"}]
                 "/common/topic/article" [{"source_uri" ["http://wp/en/68493"]}]})
      
      (defn specter-extract [case]
        {:case (case "name")
         :plaintiffs (select ["/law/legal_case/parties"
                              ALL
                              (selected? "role" ALL "id" (pred= "/en/plaintiff"))
                              "parties"
                              ALL]
                             case)
         ; etc
         })
      

      用法:

      stackoverflow-answers.core=> (specter-extract case)
      {:case "Roe v. Wade", :plaintiffs ["Norma McCorvey"]}
      

      【讨论】:

        猜你喜欢
        • 2019-06-15
        • 2014-04-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-19
        • 1970-01-01
        • 1970-01-01
        • 2013-08-04
        相关资源
        最近更新 更多