微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

clojure – 从嵌套映射(和向量)创建HTML表

我正在尝试创建一个我之前使用 python编写的表(工作计划表),我认为这对我来说是一个很好的Clojure语言介绍.

我在Clojure(或者那个问题上的lisp)方面经验很少,而且我已经完成了谷歌和一些试验和错误,但似乎无法理解这种编码风格.

这是我的示例数据(将来会来自sqlite数据库):

(def smpl2 (ref {"Salaried" 
             [{"John Doe" ["12:00-20:00" nil nil nil "11:00-19:00"]}
              {"Mary Jane" [nil "12:00-20:00" nil nil nil "11:00-19:00"]}]
             "Shift Manager"
             [{"Peter Simpson" ["12:00-20:00" nil nil nil "11:00-19:00"]}
              {"Joe Jones" [nil "12:00-20:00" nil nil nil "11:00-19:00"]}]
             "Other"
             [{"Super Man" ["07:00-16:00" "07:00-16:00" "07:00-16:00" 
                       "07:00-16:00" "07:00-16:00"]}]}))

我试图通过这个最初使用然后转移到doseq和最终domap(这似乎更成功)并将内容转储到html表(我的原始python程序从sqlite数据库输出到使用COM的excel电子表格).

这是我的尝试(create-table fn):

(defn html-doc [title & body] 
  (html (doctype "xhtml/transitional") 
    [:html [:head [:title title]] [:body body]])) 

(defn create-table []
  [:h1 "Schedule"]
  [:hr]
  [:table (:style "border: 0; width: 90%")
   [:th "Name"][:th "Mon"][:th "Tue"][:th "Wed"]
   [:th "Thur"][:th "Fri"][:th "Sat"][:th "Sun"]
   [:tr
    (domap [ct @smpl2] 
       [:tr [:td (key ct)]
        (domap [cl (val ct)]
           (domap [c cl]
              [:tr [:td (key c)]]))])
    ]])

(defroutes tstr
  (GET "/" ((html-doc "Sample" create-table)))
  (ANY "*" 404))

这会输出带有部分(工资,经理等)和章节中的名称的表格,我只是觉得我通过嵌套太多次来滥用domap,因为我可能需要添加更多的domaps才能获得在适当的列和代码中的转换时间对它来说是一种“肮脏”的感觉.

如果我没有提供足够的信息,我会提前道歉,我通常不会在编码方面寻求帮助,这也是我的第一个问题:).

如果你知道任何更好的方法来做到这一点,甚至提示或技巧,我应该知道作为一个新手,他们肯定是受欢迎的.

谢谢.

解决方法

没有办法避免某种嵌套循环.但是你根本不需要domap,Compojure足够聪明(有时)为你扩展seq.列表和地图就足够了.例如Michałmarczyk的回答,或者:
(defn map-tag [tag xs]
  (map (fn [x] [tag x]) xs))

(defn create-table []
  (list
   [:h1 "Schedule"]
   [:hr]
   [:table {:style "border: 0; width: 90%"}
    [:tr (map-tag :th ["Name" "Mon" "Tue" "Wed" "Thu" "Fri" "Sat" "Sun"])]
    [:tr (for [[category people] smpl2]
           (list* [:tr [:td category]]
                  (for [person people
                        [name hours] person]
                    [:tr [:td name] (map-tag :td hours)])))]]))

“在seq上映射并将所有内容包装在同一个标​​签中”模式很常见,我有时会喜欢使用辅助函数.

Compojure为您扩展了一个seq级别.因此,您可以将一些内容放入列表中,以便在HTML输出中按顺序显示标记,这样我就可以显示h1和hr.在你的代码中,你只是扔掉了h1和hr.

但请注意,它只扩展了一个级别.当你有一个列表列表或一个seq列表时,外部seq将会扩展,但内部seq将不会.

user> (println (html (list [:div "foo"] (for [x [1 2 3]] [:div x]))))
<div>foo</div>clojure.lang.LazySeq@ea73bbfd

看看内部seq如何制作Compojure barf.查看compojure.html.gen / expand-seqs以查看其工作原理,或者如果您愿意,可以更改/修复它.

当您在列表中嵌套for或for时,这可能是一个问题,因为返回一个惰性seq.但你必须避免使用seq-in-a-seq.我使用上面的列表*. list和html的组合也可以使用.还有很多其他方法.

user> (println (html (list* [:div "foo"] (for [x [1 2 3]] [:div x]))))
<div>foo</div><div>1</div><div>2</div><div>3</div>

user> (println (html (list [:div "foo"] (html (for [x [1 2 3]] [:div x])))))
<div>foo</div><div>1</div><div>2</div><div>3</div>

原文地址:https://www.jb51.cc/html/227197.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐