使用postwalk

时间:2015-07-22 02:35:30

标签: clojure

我有一棵树,其结构类似于以下结构:

(def tree
  [:ul
   [:li
    [:input]]
   [:li
    [:input]]])

我想在每个[:input]之后插入一个[:button]:

[:ul
 [:li
  [:input]
  [:button]]
 [:li
  [:input]
  [:button]]

我写了以下代码:

 (postwalk
  (fn [x]
    (if (and (vector? x) (= :input (first x)))
      (list x [:button])
      x))
  tree)

产生:

[:ul
 [:li
  ([:input] [:button])]
 [:li
  ([:input] [:button])]]

几乎我想要什么,除了[:input]和[:button]向量 现在列在清单中。

是否有惯用的方法来插入""两个节点,而不必将它们放在一个列表中?

(注意:Hiccup用当前结果生成所需的标记,但我想避免破坏我的树。)

1 个答案:

答案 0 :(得分:5)

如果在[:input]级别进行替换,则无法避免列表(或向量),因为fn的结果将始终是单个元素。您需要列表包含两个元素。

另一种方法是在[:li]级别进行替换:

(postwalk
  (fn [x]
    (if (and (vector? x) (= :li (first x)) (= :input (ffirst (rest x))))
      (conj x [:button])
      x))
  tree)

如果你真的想避开这个列表的话。正如你所说,在打嗝的情况下,它与列表一起工作正常。我不担心。