首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Clojure中遍历多分支树并收集数据?

如何在Clojure中遍历多分支树并收集数据?
EN

Stack Overflow用户
提问于 2021-05-23 12:10:30
回答 1查看 119关注 0票数 0

我需要将json转换为另一种格式,所以我使用instaparse将json转换为向量列表。

原始json:

代码语言:javascript
复制
[
  {
    "k1": "v1",
    "k2": {
      "k21": "v21",
      "k22": "v22"
    }
  },
  {
    "k4": "v4",
    "k5": "v5",
    "k6": "v6"
  }
]

转换为clojure向量列表:

代码语言:javascript
复制
[:JSON
 [:ARRAY
  [:OBJECT
   [:KEY_VALUE_PAIR [:STRING "\"k1\""] [:STRING "\"v1\""]]
   [:KEY_VALUE_PAIR
    [:STRING "\"k2\""]
    [:OBJECT
     [:KEY_VALUE_PAIR [:STRING "\"k21\""] [:STRING "\"v21\""]]
     [:KEY_VALUE_PAIR [:STRING "\"k22\""] [:STRING "\"v22\""]]]]]
  [:OBJECT
   [:KEY_VALUE_PAIR [:STRING "\"k4\""] [:STRING "\"v4\""]]
   [:KEY_VALUE_PAIR [:STRING "\"k5\""] [:STRING "\"v5\""]]
   [:KEY_VALUE_PAIR [:STRING "\"k6\""] [:STRING "\"v6\""]]]]]

可视化此链接中的树:visualizing tree

我想要这样的格式:

代码语言:javascript
复制
[
  {
    k1: "k1",
    k2: {
      k21: "k2.k21",
      k22: "k2.k22"
    }
  },
  {
    k4: "k4",
    k5: "k5",
    k6: "k6"
  }
]

那么,如何在Clojure中遍历多分支树并收集数据呢?我发现它很少使用tree-seq和walk函数,所以我试着写代码:

代码语言:javascript
复制
(ns clojure.examples.hello
    (:gen-class))
    
(def json-tree [:JSON [:ARRAY [:OBJECT [:KEY_VALUE_PAIR [:STRING "\"k1\""] [:STRING "\"v1\""]] [:KEY_VALUE_PAIR [:STRING "\"k2\""] [:OBJECT [:KEY_VALUE_PAIR [:STRING "\"k21\""] [:STRING "\"v21\""]] [:KEY_VALUE_PAIR [:STRING "\"k22\""] [:STRING "\"v22\""]]]]] [:OBJECT [:KEY_VALUE_PAIR [:STRING "\"k4\""] [:STRING "\"v4\""]] [:KEY_VALUE_PAIR [:STRING "\"k5\""] [:STRING "\"v5\""]] [:KEY_VALUE_PAIR [:STRING "\"k6\""] [:STRING "\"v6\""]]]]])

(defn transform-key [x]
    (-> x
        (clojure.string/replace "\"" "")
        (clojure.string/upper-case)))

(defn transform-value [x]
    (if (= x "") x (str x ".")))

(defn bf3 "return elements in tree, breath-first"
    [[el & children :as tree] path] ;; a tree is a seq of one element,
                     ;; followed by left and right child trees
    (if (nil? el)
        (do)
        (if (= el :JSON)
            (do (print (get (vec children) 0))
                (bf3 (get (vec children) 0) path))
                (if (= el :ARRAY)
                    (let [[first & rest-list] (get (vec children) 0)
                            rest (vec rest-list)]
                        (do (print "[") (bf3 first path) (bf3 rest path) (print "], ")))
                    (if (= el :OBJECT)
                        (let [[_ [_ key] & rest-list] (get (vec children) 0)
                            [rest] (vec rest-list)]
                            (do (print "{") 
                                (print (str (transform-key key) ": "))
                                (print (str "rest====>" rest))
                                (bf3 rest (transform-key key))
                                (print "}, ")))
                        (if (= el :KEY_VALUE_PAIR)
                            (do (print (str (transform-key (get first 1)) ": ")) 
                                (bf3 rest (str (transform-value path) (transform-key (get first 1)))))
                            (print (str "\"" path "\", "))))))))

(bf3 json-tree "")

但这段代码似乎只能遍历一个分支,其余分支则不能遍历。

EN

回答 1

Stack Overflow用户

发布于 2021-06-05 02:39:12

您绝对应该考虑使用clojure.walk

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67656049

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档