我在clojure中有一个地图数据结构:
{:category_id 1,:name“ELECTRONICS”,:lft 1,:rgt 20,:children [{:category_id 6,:name“PORTABLE ELECTRONICS”,:lft 10,:rgt 19,:children [{:children [{:rgt 13,:lft 12,:name“FLASH”,:category_id 8}],:category_id 7,:name“MP3 PLAYERS”,:lft 11,:rgt 14} {:rgt 18, :lft 17,:名称“2 WAY RADIOS”,:category_id 10} {:rgt 16,:lft 15,:name“CD PLAYERS”,:category_id 9}]} {:children [{:rgt 6,:lft 5 ,:name“LCD”,:category_id 4} {:rgt 8,:lft 7,:name“PLASMA”,:category_id 5} {:rgt 4,:lft 3 ,: name“TUBE”,:category_id 3}] ,:rgt 9,:lft 2 ,: name“TELEVISIONS”,:category_id 2}]}
我想将一些数据(与类别相关联的产品)附加到作为产品类别的所有叶节点,以便它看起来像这样:
{:category_id 1,:name“ELECTRONICS”,:lft 1,:rgt 20,:children [{:category_id 6,:name“PORTABLE ELECTRONICS”,:lft 10,:rgt 19,:children [{:children [{:rgt 13,:lft 12,:name“FLASH”,:category_id 8}],:category_id 7,:name“MP3 PLAYERS”,:lft 11,:rgt 14:products [{:name “SONY MP3 PLAYER”} {:name“SONY MP3 PLAYER 2”}}} {:rgt 18,:lft 17,:name“2 WAY RADIOS”,:category_id 10} {:rgt 16,:lft 15,:name “CD播放器”,:category_id 9}]} {:children [{:rgt 6,:lft 5,:name“LCD”,:category_id 4} {:rgt 8,:lft 7,:name“PLASMA”,: category_id 5} {:rgt 4,:lft 3,:name“TUBE”,:category_id 3}],:rgt 9,:lft 2,:name“TELEVISIONS”,:category_id 2}]}
我已将两个产品添加到叶节点“MP3播放器”
如何使用clojure实现这一目标?如果不是clojure,我可以用任何其他编程语言获得解决方案吗?像Python等。?
答案 0 :(得分:2)
假设您不知道您的类别位于层次结构中的哪个位置,您可以使用此方法:
(use 'clojure.walk)
(defn add-to-category
[catalog cat-id product]
(postwalk (fn [x]
(if (and (map? x)
(= (:category_id x) cat-id))
(update-in x [:products] conj product)
x))
catalog))
这是您的初始地图:
(def my-catalog {:children
[{:children
[{:children [{:name "FLASH", :lft 12, :category_id 8, :rgt 13}],
:name "MP3 PLAYERS",
:lft 11,
:category_id 7,
:rgt 14}
{:name "2 WAY RADIOS", :lft 17, :category_id 10, :rgt 18}
{:name "CD PLAYERS", :lft 15, :category_id 9, :rgt 16}],
:name "PORTABLE ELECTRONICS",
:lft 10,
:category_id 6,
:rgt 19}
{:children
[{:name "LCD", :lft 5, :category_id 4, :rgt 6}
{:name "PLASMA", :lft 7, :category_id 5, :rgt 8}
{:name "TUBE", :lft 3, :category_id 3, :rgt 4}],
:name "TELEVISIONS",
:lft 2,
:category_id 2,
:rgt 9}],
:name "ELECTRONICS",
:lft 1,
:category_id 1,
:rgt 20}
调用为:
(add-to-category my-catalog 7 {:name "SONY MP3 PLAYER 2"})
答案 1 :(得分:-1)
这看起来像是update-in
的工作。
(def categories {:category_id 1, :name "ELECTRONICS", :lft 1, :rgt 20, :children [{:category_id 6, :name "PORTABLE ELECTRONICS", :lft 10, :rgt 19, :children [{:children [{:rgt 13, :lft 12, :name "FLASH", :category_id 8}], :category_id 7, :name "MP3 PLAYERS", :lft 11, :rgt 14} {:rgt 18, :lft 17, :name "2 WAY RADIOS", :category_id 10} {:rgt 16, :lft 15, :name "CD PLAYERS", :category_id 9}]} {:children [{:rgt 6, :lft 5, :name "LCD", :category_id 4} {:rgt 8, :lft 7, :name "PLASMA", :category_id 5} {:rgt 4, :lft 3, :name "TUBE", :category_id 3}], :rgt 9, :lft 2, :name "TELEVISIONS", :category_id 2}]})
(update-in categories [:children 0 :children 0 :products]
conj {:name "SONY MP3 PLAYER"} {:name "SONY MP3 PLAYER 2"})
;; Returns a similar giant map. Here with clojure.pprint/pprint formatting:
{:category_id 1,
:name "ELECTRONICS",
:lft 1,
:rgt 20,
:children
[{:category_id 6,
:name "PORTABLE ELECTRONICS",
:lft 10,
:rgt 19,
:children
[{:products ({:name "SONY MP3 PLAYER 2"} {:name "SONY MP3 PLAYER"}),
:children [{:rgt 13, :lft 12, :name "FLASH", :category_id 8}],
:category_id 7,
:name "MP3 PLAYERS",
:lft 11,
:rgt 14}
{:rgt 18, :lft 17, :name "2 WAY RADIOS", :category_id 10}
{:rgt 16, :lft 15, :name "CD PLAYERS", :category_id 9}]}
{:children
[{:rgt 6, :lft 5, :name "LCD", :category_id 4}
{:rgt 8, :lft 7, :name "PLASMA", :category_id 5}
{:rgt 4, :lft 3, :name "TUBE", :category_id 3}],
:rgt 9,
:lft 2,
:name "TELEVISIONS",
:category_id 2}]}
如果您特别需要:products
作为向量,那么您希望代替conj
使用创建向量的函数(如果它已通过nil
}作为第一个参数。 conj
should work this way starting in 1.7,但我必须提供的测试时间早于此。