如何使用幽灵合并两个不同的集合?
How to merge two different collections using specter?
我正在尝试编写一个合并方法来动态生成 CSS 样式。此方法应采用 breakpoints,
和 styles
参数并创建一个地图,我们将其用于使用 stylefy 进行样式设置。
我正在尝试使用 spectre 执行此操作,但无法获得所需的结果。
到目前为止我尝试的代码:
(defn merge-style
[breakpoints style]
(let [media-queries (s/transform [s/ALL] #(hash-map :min-width (str %1 "px")) breakpoints)]
breakpoints))
该方法的工作原理如下:
(def breakpoints ["320px" "600px" "1280px"])
(def style {:padding-top ["20px" "30px" "40px" "50px"]
:margin "30px"
})
(merge-style breakpoints style)
输出应如下所示:
{:padding-top "20px"
:margin "30px"
::stylefy/media {{:min-width "320px"} {:padding-top "30px"}
{:min-width "600px"} {:padding-top "40px"}
{:min-width "1280px"} {:padding-top "50px"}}
}
解决方案:
我使用以下函数为自己解决了这个问题
(defn- get-media-queries
[breakpoints styles]
(let [base-style (s/transform [s/MAP-VALS] #(%1 0) styles)
styles-maps (s/setval [s/MAP-VALS empty?] s/NONE (s/setval [s/MAP-VALS s/FIRST] s/NONE styles))
styles-list (map (fn [[key val]] (map #(hash-map key %1) val)) styles-maps)
styles-final (apply vdu/merge-maps styles-list)
breaks (map #(hash-map :min-width %1) breakpoints)
styles-merged (into {} (mapv vector breaks styles-final))
]
(assoc base-style ::stylefy/media styles-merged)))
非常感谢提供帮助。
这个不需要 Spectre。只需使用基本的 Clojure:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test) )
(def desired
{:padding-top "20px"
:margin "30px"
:stylefy/media {{:min-width "320px"} {:padding-top "30px"}
{:min-width "600px"} {:padding-top "40px"}
{:min-width "1280px"} {:padding-top "50px"}}})
(def breakpoints [320 600 1280])
(def padding-top ["30px" "40px" "50px"])
(def base {:padding-top "20px"
:margin "30px"})
(dotest
(let [mw (for [it breakpoints]
{:min-width (str it "px")})
pt (for [it padding-top]
{:padding-top it})
pairs (zipmap mw pt)
result (assoc base :stylefy/media pairs)]
(is= desired result)))
请注意,由于我没有 stylefy
的命名空间别名,我只使用关键字的单冒号版本。
2019-9-12更新
刚刚重温此 post,并注意到我应该使用 zipmap
而不是 zip
,即使以前的版本(不小心!)得到了正确的答案。
我正在尝试编写一个合并方法来动态生成 CSS 样式。此方法应采用 breakpoints,
和 styles
参数并创建一个地图,我们将其用于使用 stylefy 进行样式设置。
我正在尝试使用 spectre 执行此操作,但无法获得所需的结果。
到目前为止我尝试的代码:
(defn merge-style
[breakpoints style]
(let [media-queries (s/transform [s/ALL] #(hash-map :min-width (str %1 "px")) breakpoints)]
breakpoints))
该方法的工作原理如下:
(def breakpoints ["320px" "600px" "1280px"])
(def style {:padding-top ["20px" "30px" "40px" "50px"]
:margin "30px"
})
(merge-style breakpoints style)
输出应如下所示:
{:padding-top "20px"
:margin "30px"
::stylefy/media {{:min-width "320px"} {:padding-top "30px"}
{:min-width "600px"} {:padding-top "40px"}
{:min-width "1280px"} {:padding-top "50px"}}
}
解决方案: 我使用以下函数为自己解决了这个问题
(defn- get-media-queries
[breakpoints styles]
(let [base-style (s/transform [s/MAP-VALS] #(%1 0) styles)
styles-maps (s/setval [s/MAP-VALS empty?] s/NONE (s/setval [s/MAP-VALS s/FIRST] s/NONE styles))
styles-list (map (fn [[key val]] (map #(hash-map key %1) val)) styles-maps)
styles-final (apply vdu/merge-maps styles-list)
breaks (map #(hash-map :min-width %1) breakpoints)
styles-merged (into {} (mapv vector breaks styles-final))
]
(assoc base-style ::stylefy/media styles-merged)))
非常感谢提供帮助。
这个不需要 Spectre。只需使用基本的 Clojure:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test) )
(def desired
{:padding-top "20px"
:margin "30px"
:stylefy/media {{:min-width "320px"} {:padding-top "30px"}
{:min-width "600px"} {:padding-top "40px"}
{:min-width "1280px"} {:padding-top "50px"}}})
(def breakpoints [320 600 1280])
(def padding-top ["30px" "40px" "50px"])
(def base {:padding-top "20px"
:margin "30px"})
(dotest
(let [mw (for [it breakpoints]
{:min-width (str it "px")})
pt (for [it padding-top]
{:padding-top it})
pairs (zipmap mw pt)
result (assoc base :stylefy/media pairs)]
(is= desired result)))
请注意,由于我没有 stylefy
的命名空间别名,我只使用关键字的单冒号版本。
2019-9-12更新
刚刚重温此 post,并注意到我应该使用 zipmap
而不是 zip
,即使以前的版本(不小心!)得到了正确的答案。