【问题标题】:Building nested vector from map in Clojure在 Clojure 中从地图构建嵌套向量
【发布时间】:2017-11-02 21:19:04
【问题描述】:

我有一组 URL,其中一些 URL 具有间接引用(作为向量)。任何没有间接引用的 URL 都只有nil。我从以下测试地图开始:

{"URL 1" nil,
 "URL 2" ["indirect 1" "indirect 2"]}

我正在使用hiccup 构建一个 HTML 报告,所以我想要这个输出:

[:div "Imports: "
 [:ul
  [:li "URL 1"]
  [:li "URL 2"]
    [:ul
     [:li "indirect 1"]
     [:li "indirect 2"]
     [:li "indirect 3"]]]]

当 URL 没有间接引用时,我遇到了一些返回 nil 的问题。我当前的代码如下所示:

(defn list-imports
  [imports]
  (if-not (nil? imports)
    [:div "Imports: "
     [:ul
      (for [direct (keys imports)]
        [[:li direct]
         (if-let [indirects (get imports direct)]
           [:ul
             (for [indirect indirects]
               [:li indirect])]
           [:span])])]]
    [:div "Imports: none" [:br] [:br]]))

问题是,它正在返回这个......

[:div
 "Imports: "
 [:ul
  ([[:li "URL 1"] [:span]]
   [[:li "URL 2"] [:ul ([:li "indirect 1"] [:li "indirect 2"])]])]]

当间接导入为nil 时,我必须添加一个[:span] 标记,我真的不想在那里...但否则,它会将nil 放在那里。

另一个问题是它最终包含在() 和一个额外的向量中,因为我在 for 语句中做了很多事情。当我尝试用打嗝转换它时,我得到[:li "URL 1"] is not a valid element name.

【问题讨论】:

    标签: clojure functional-programming hiccup


    【解决方案1】:

    这可能是构建打嗝标签的一个棘手方面。有时它有助于将问题分解成更小的部分。

    (defn list-indirects
      [indirects]
      (when (seq indirects)
        [(into [:ul] (mapv (fn [i] [:li i]) indirects))]))
    
    (defn list-imports
      [imports]
      (if (some? imports)
        [:div "Imports: "
         (into [:ul]
           (for [[url indirects] imports]
             (into [:li url] (list-indirects indirects))))]
        [:div "Imports: none" [:br] [:br]]))
    

    这些函数应该会给你想要的输出。

    (list-imports {"URL 1" nil
                   "URL 2" ["indirect 1" "indirect 2"]})
    =>
    [:div "Imports: "
     [:ul
      [:li "URL 1"]
      [:li "URL 2"
       [:ul
        [:li "indirect 1"]
        [:li "indirect 2"]]]]]
    

    此输出与您的预期输出略有不同,但我认为它更接近您实际想要的,即您的示例中的 [:li "URL 2"] 标签应该包含“indirects”的:ul " 是有效的 HTML。

    如果这些项目的顺序很重要,需要注意的另一件事是,地图可能不会以您期望的方式排序,尤其是当您拥有超过一定数量的键时。当您遍历地图构建打嗝时,"URL 2" 可能会出现在之前 "URL 1"。您可以通过使用元组向量或排序映射来解决此问题。

    【讨论】:

    • 效果很好,非常感谢!我想我试图过多地融入一项功能。我什至没有想过使用mapv,但现在看起来很明显:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-18
    • 2014-04-30
    • 1970-01-01
    • 2016-11-14
    • 2016-02-01
    • 1970-01-01
    相关资源
    最近更新 更多