Clojure:创建从记录中提取的值列表

时间:2017-11-12 17:26:44

标签: xml clojure

我有一个类型" clojure.data.xml.Element"的数据结构。看起来像这样(漂亮印刷):

{:tag :eSearchResult,
 :attrs {},
 :content
 ({:tag :Count, :attrs {}, :content ("16")}
  {:tag :RetMax, :attrs {}, :content ("16")}
  {:tag :RetStart, :attrs {}, :content ("0")}
  {:tag :IdList,
   :attrs {},
   :content
   ({:tag :Id, :attrs {}, :content ("28911150")}
    {:tag :Id, :attrs {}, :content ("28899394")}
    {:tag :Id, :attrs {}, :content ("28597238")}
    {:tag :Id, :attrs {}, :content ("28263281")}
    {:tag :Id, :attrs {}, :content ("28125459")}
    {:tag :Id, :attrs {}, :content ("26911135")}
    {:tag :Id, :attrs {}, :content ("26699345")}
    {:tag :Id, :attrs {}, :content ("26297102")}
    {:tag :Id, :attrs {}, :content ("26004019")}
    {:tag :Id, :attrs {}, :content ("25995331")}
    {:tag :Id, :attrs {}, :content ("25429093")}
    {:tag :Id, :attrs {}, :content ("25355095")}
    {:tag :Id, :attrs {}, :content ("25224593")}
    {:tag :Id, :attrs {}, :content ("24816246")}
    {:tag :Id, :attrs {}, :content ("24779721")}
    {:tag :Id, :attrs {}, :content ("24740865")})}

如何从这些记录中提取ID?换句话说,创建一个获取此数据结构并返回Id字符串列表的函数(" 28911150"" 28899394" ...)?

感谢。

3 个答案:

答案 0 :(得分:5)

您可以使用Clojure的基本数据访问器实现这一目标:

(->> data                            ; the input
     :content                        ; the content list
     (filter #(= :IdList (:tag %)))  ; only the IdLists
     (mapcat :content)               ; their content as one list
     (filter #(= :Id (:tag %)))      ; only the Ids
     (mapcat :content))              ; one long list of the strings therein

答案 1 :(得分:3)

如果您愿意添加额外的库,可以使用specter来完成此操作:

savePitch(e){
        this.setState({savedPitches: [...this.state.savedPitches, this.state.addNewPitch]})
        this.setState({addNewPitch: {
            id: this.state.addNewPitch.id + 1,
            pitchName: '',
            shortCut: '',
            subject: '',
            pitch: ''
        }},
        () => {console.log('this worked')},
        () => {console.log('then this worked')},
        )
        this.toggleNewPitchForm()
    }

答案 2 :(得分:0)

specter外,您还可以use the tupelo.forest library

(dotest
  (with-forest (new-forest)
    (let [root-hid   (add-tree-enlive
                       {:tag     :eSearchResult,
                        :attrs   {},
                        :content [
                            {:tag :Count, :attrs {}, :content ["16"]}
                            {:tag :RetMax, :attrs {}, :content ["16"]}
                            {:tag :RetStart, :attrs {}, :content ["0"]}
                            {:tag     :IdList,
                             :attrs   {},
                             :content [
                                 {:tag :Id, :attrs {}, :content ["28911150"]}
                                 {:tag :Id, :attrs {}, :content ["28899394"]}
                                 {:tag :Id, :attrs {}, :content ["28597238"]}
                                 {:tag :Id, :attrs {}, :content ["28263281"]}
                                 {:tag :Id, :attrs {}, :content ["28125459"]}
                                 {:tag :Id, :attrs {}, :content ["26911135"]}
                                 {:tag :Id, :attrs {}, :content ["26699345"]}
                                 {:tag :Id, :attrs {}, :content ["26297102"]}
                                 {:tag :Id, :attrs {}, :content ["26004019"]}
                                 {:tag :Id, :attrs {}, :content ["25995331"]}
                                 {:tag :Id, :attrs {}, :content ["25429093"]}
                                 {:tag :Id, :attrs {}, :content ["25355095"]}
                                 {:tag :Id, :attrs {}, :content ["25224593"]}
                                 {:tag :Id, :attrs {}, :content ["24816246"]}
                                 {:tag :Id, :attrs {}, :content ["24779721"]}
                                 {:tag :Id, :attrs {}, :content ["24740865"]} ]}]})

我们可以找到从根到每个Id元素的路径,然后用2行代替ID字符串:

          id-content-paths (find-paths root-hid [:eSearchResult :IdList :Id])
          id-strings       (forv [path id-content-paths]
                             (grab :value (hid->leaf (last path))))]

hid->bush函数打印数据树的类似打嗝的表示:

  (is= (hid->bush root-hid)
        [{:tag :eSearchResult}
         [{:tag :Count, :value "16"}]
         [{:tag :RetMax, :value "16"}]
         [{:tag :RetStart, :value "0"}]
         [{:tag :IdList}
          [{:tag :Id, :value "28911150"}]
          [{:tag :Id, :value "28899394"}]
          [{:tag :Id, :value "28597238"}]
          [{:tag :Id, :value "28263281"}]
          [{:tag :Id, :value "28125459"}]
          [{:tag :Id, :value "26911135"}]
          [{:tag :Id, :value "26699345"}]
          [{:tag :Id, :value "26297102"}]
          [{:tag :Id, :value "26004019"}]
          [{:tag :Id, :value "25995331"}]
          [{:tag :Id, :value "25429093"}]
          [{:tag :Id, :value "25355095"}]
          [{:tag :Id, :value "25224593"}]
          [{:tag :Id, :value "24816246"}]
          [{:tag :Id, :value "24779721"}]
          [{:tag :Id, :value "24740865"}]]])

此单元测试显示了所需的结果:

  (is= id-strings
        ["28911150"
         "28899394"
         "28597238"
         "28263281"
         "28125459"
         "26911135"
         "26699345"
         "26297102"
         "26004019"
         "25995331"
         "25429093"
         "25355095"
         "25224593"
         "24816246"
         "24779721"
         "24740865"])
      )))