首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从嵌套映射(和向量)创建HTML表

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

Stack Overflow用户
提问于 2010-03-14 22:57:19
回答 2查看 3.5K关注 0票数 8

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

我对Clojure (或lisp在这个问题上的经验)很少,我在google上做过很多次尝试和错误的尝试,但我似乎无法理解这种编码风格。

以下是我的示例数据(将来将来自sqlite数据库):

代码语言:javascript
运行
复制
(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"]}]}))

我最初尝试使用for来完成这个过程,然后转到doseq,最后是domap (这似乎更成功),并将内容转储到html表中(我最初的python程序使用COM将其从sqlite数据库输出到excel电子表格中)。

下面是我的尝试(创建表fn):

代码语言:javascript
运行
复制
(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,嵌套了太多次,因为我可能需要添加更多的domap,以便在它们正确的列中获得转换时间,并且代码对其有一种“肮脏”的感觉。

我事先道歉,如果我没有包括足够的信息,我通常不要求帮助编码,这也是我的第一个这么问:)。

如果你知道更好的方法来做这件事,甚至是我作为新手应该知道的技巧或技巧,它们绝对是受欢迎的。

谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-03-15 07:43:35

没有办法避免某种嵌套循环。但是您根本不需要domap,Compojure很聪明(有时)可以为您展开一个seq。listmapfor就足够了。例如,MichałMarczyk的答案,或:

代码语言:javascript
运行
复制
(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。因此,您可以将一些东西扔到list中,以获取标记,以便在您的HTML中依次显示,我是这样做的,以使h1和hr显示出来。在您的代码中,您只是将h1和hr抛出。

但请注意,它只扩展了一个级别。当您有一个列表或seq列表时,外部seq将展开,而内部seq则不会。

代码语言:javascript
运行
复制
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以了解它是如何工作的,如果您愿意的话,可以更改/修复它。

当您在forfor中嵌套list时,这可能是一个问题,因为for返回一个延迟的seq。但你只需要避免吃塞克。我使用上面的list*listhtml的结合也会奏效。还有很多其他的方法。

代码语言:javascript
运行
复制
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>
票数 4
EN

Stack Overflow用户

发布于 2010-03-15 01:57:10

我认为您的代码有一些小问题。我已经尝试在下面的代码中纠正它们。在Compojure 0.3.2中测试这一点,我敢说它可以工作。(当然,你可以自由地指出任何需要改进或似乎不适合你的地方。)

代码语言:javascript
运行
复制
(use 'compojure) ; you'd use a ns form normally

;;; I'm not using a ref here; this doesn't change much,
;;; though with a ref / atom / whatever you'd have to take care
;;; to dereference it once per request so as to generate a consistent
;;; (though possibly outdated, of course) view of data;
;;; this doesn't come into play here anyway
(def smpl2 {"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"]}]})

(defn html-doc [title & body] 
  (html (doctype :xhtml-transitional) ; the idiomatic way to insert
                                      ; the xtml/transitional doctype
        [:html
         [:head [:title title]]
         [:body body]]))

(defn create-table []
  (html
   [:h1 "Schedule"]
   [:hr]
   [:table {:style "border: 0; width: 90%;"}
    [:tr
     [:th "Name"][:th "Mon"][:th "Tue"][:th "Wed"]
     [:th "Thur"][:th "Fri"][:th "Sat"][:th "Sun"]]
    (for [category smpl2]
      [:div [:tr [:td (key category)]] ; for returns just one thing per
                                       ; 'iteration', so I'm using a div
                                       ; to package two things together;
                                       ; it could be avoided, so tell me
                                       ; if it's a problem
       (for [people (val category)]
         (for [person people]
           [:tr
            [:td (key person)]
            (for [hours (val person)]
              [:td hours])]))])]))

(defn index-html [request]
  (html-doc "Sample" (create-table)))

(defroutes test-routes
  (GET "/" index-html)
  (ANY "*" 404))

(defserver test-server
  {:port 8080}
  "/*"
  (servlet test-routes))
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2444170

复制
相关文章

相似问题

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