移动分区依据的拆分 "back by one"
Moving partition-by's splits "back by one"
我正在 CLJS 中解析一些 Hiccup,目的是获取 :h2
和 :h3
元素并将它们转换为嵌套的 :ul
和 :li
树.
我的起点是平面矢量,例如:
[[:h2 {} "Foo"] [:h2 {} "Bar"] [:h3 {} "Child1"] [:h2 {} "Baz"]]
如果我只是映射这些并将 (first el)
替换为 [:li]
,我有一个简单的列表。但我想得到类似的东西:
[[:li "Foo"] [:li "Bar"] [:ul [:li "Child1"]] [:li "Baz"]]
如果我调用 (partition-by #(= :h2 (first %)) my-vec)
,我会得到一些几乎有用的东西:
(([:h2 {} "Foo"] [:h2 {} "Bar"]) ([:h3 {} "Child1"]) ([:h2 {} "Baz"]))
分区发生在谓词 #(= :h2 (first %))
发生变化时,(这是文档所说的)。
如何获得我正在寻找的行为?
这是一种方法:
(def data [
[:h2 {} "Foo"]
[:h2 {} "Bar"]
[:h3 {} "Child1"]
[:h2 {} "Baz"] ] )
(defn formatter [elem]
(condp = (first elem)
:h2 [:li (last elem)]
:h3 [:ul [:li (last elem)]]
))
(newline) (println :data data)
(newline) (println :result (mapv formatter data))
结果
:data [[:h2 {} Foo] [:h2 {} Bar] [:h3 {} Child1] [:h2 {} Baz]]
:result [[:li Foo] [:li Bar] [:ul [:li Child1]] [:li Baz]]
更新:
像这样重写以将所有 :h3
项目合而为一 :ul
(def data [
[:h2 {} "Foo"]
[:h3 {} "Child1"]
[:h2 {} "Bar"]
[:h3 {} "Child2"]
[:h3 {} "Child3"]
[:h2 {} "Baz"] ] )
(defn h2? [elem]
(= :h2 (first elem)))
(defn ->li [elem]
[:li (last elem)])
(defn fmt [data]
(let [h2 (filter h2? data)
h3 (filter #(not (h2? %)) data)
result (conj (mapv ->li h2)
(apply vector :ul (mapv ->li h3))) ]
result ))
(newline) (println :data data)
(newline) (println :result (fmt data))
结果
:data [[:h2 {} Foo] [:h3 {} Child1] [:h2 {} Bar] [:h3 {} Child2] [:h3 {} Child3] [:h2 {} Baz]]
:result [[:li Foo] [:li Bar] [:li Baz] [:ul [:li Child1] [:li Child2] [:li Child3]]]
这是一个可以完成工作的答案,但非常不优雅,因为它在必要时实质上改变了 reduce
调用中的最后一个元素:
(defn listify-element [element]
"Replaces element type with :li."
(vec (concat [:li (last element))]))
(defn listify-headings [headings-list]
"Takes subitems (in :h2 :h3) and creates sub :uls out of the :h3 lists."
(vec
(concat
[:ul]
(map-indexed
(fn [ind headings]
(if (= 0 (mod ind 2))
(map listify-element headings)
(vec (concat [:ul] (map listify-element headings)))))
(partition-by #(= :h2 (first %)) headings-list)))))
(defn nest-listified-headings [vector-list]
"Nests sub-:uls inside their preceding :lis."
(vec (concat [:ul]
(reduce
(fn [acc el] (if (= (first el) :ul)
(conj (pop (vec acc)) (conj (last acc) el))
(concat acc el)))
vector-list))))
生产:
(nest-listified-headings
(listify-headings [[:h2 "Foo"] [:h2 "Bar"] [:h3 "Baz"] [:h3 "Bat"]])
[:ul [:li "Foo"]
[:li "Bar"
[:ul
[:li "Baz"]
[:li "Bat"]]]]
我正在 CLJS 中解析一些 Hiccup,目的是获取 :h2
和 :h3
元素并将它们转换为嵌套的 :ul
和 :li
树.
我的起点是平面矢量,例如:
[[:h2 {} "Foo"] [:h2 {} "Bar"] [:h3 {} "Child1"] [:h2 {} "Baz"]]
如果我只是映射这些并将 (first el)
替换为 [:li]
,我有一个简单的列表。但我想得到类似的东西:
[[:li "Foo"] [:li "Bar"] [:ul [:li "Child1"]] [:li "Baz"]]
如果我调用 (partition-by #(= :h2 (first %)) my-vec)
,我会得到一些几乎有用的东西:
(([:h2 {} "Foo"] [:h2 {} "Bar"]) ([:h3 {} "Child1"]) ([:h2 {} "Baz"]))
分区发生在谓词 #(= :h2 (first %))
发生变化时,(这是文档所说的)。
如何获得我正在寻找的行为?
这是一种方法:
(def data [
[:h2 {} "Foo"]
[:h2 {} "Bar"]
[:h3 {} "Child1"]
[:h2 {} "Baz"] ] )
(defn formatter [elem]
(condp = (first elem)
:h2 [:li (last elem)]
:h3 [:ul [:li (last elem)]]
))
(newline) (println :data data)
(newline) (println :result (mapv formatter data))
结果
:data [[:h2 {} Foo] [:h2 {} Bar] [:h3 {} Child1] [:h2 {} Baz]]
:result [[:li Foo] [:li Bar] [:ul [:li Child1]] [:li Baz]]
更新:
像这样重写以将所有 :h3
项目合而为一 :ul
(def data [
[:h2 {} "Foo"]
[:h3 {} "Child1"]
[:h2 {} "Bar"]
[:h3 {} "Child2"]
[:h3 {} "Child3"]
[:h2 {} "Baz"] ] )
(defn h2? [elem]
(= :h2 (first elem)))
(defn ->li [elem]
[:li (last elem)])
(defn fmt [data]
(let [h2 (filter h2? data)
h3 (filter #(not (h2? %)) data)
result (conj (mapv ->li h2)
(apply vector :ul (mapv ->li h3))) ]
result ))
(newline) (println :data data)
(newline) (println :result (fmt data))
结果
:data [[:h2 {} Foo] [:h3 {} Child1] [:h2 {} Bar] [:h3 {} Child2] [:h3 {} Child3] [:h2 {} Baz]]
:result [[:li Foo] [:li Bar] [:li Baz] [:ul [:li Child1] [:li Child2] [:li Child3]]]
这是一个可以完成工作的答案,但非常不优雅,因为它在必要时实质上改变了 reduce
调用中的最后一个元素:
(defn listify-element [element]
"Replaces element type with :li."
(vec (concat [:li (last element))]))
(defn listify-headings [headings-list]
"Takes subitems (in :h2 :h3) and creates sub :uls out of the :h3 lists."
(vec
(concat
[:ul]
(map-indexed
(fn [ind headings]
(if (= 0 (mod ind 2))
(map listify-element headings)
(vec (concat [:ul] (map listify-element headings)))))
(partition-by #(= :h2 (first %)) headings-list)))))
(defn nest-listified-headings [vector-list]
"Nests sub-:uls inside their preceding :lis."
(vec (concat [:ul]
(reduce
(fn [acc el] (if (= (first el) :ul)
(conj (pop (vec acc)) (conj (last acc) el))
(concat acc el)))
vector-list))))
生产:
(nest-listified-headings
(listify-headings [[:h2 "Foo"] [:h2 "Bar"] [:h3 "Baz"] [:h3 "Bat"]])
[:ul [:li "Foo"]
[:li "Bar"
[:ul
[:li "Baz"]
[:li "Bat"]]]]