我有两个案例展示了我正在使用的数据如何格式化:
案例1:
{:key ["val1" "val2" "val3"]}
案例2:
{:key {"Title1" ["Val1" "Val2"] "Title2" ["Val3" "Val4"] "Title3" []}}
我想要的是识别案例并用数据做基于案例的事情。
这就是我所拥有的:
(let [val {"Produkt" ["bla" "blub"] "Test" ["12" "34" "45"]}]
(cond
(not (= (some map? val) nil))
(for [v val]
(str v ", "))
:else
(for [v val]
(do (first v)
(for [c (second v)]
(str c ", "))))))
输出格式不正确。我不得不删除sscce的一些代码。案例2的输出应如下所示:
("Produkt" ("12, " "34, " "45, ") "Test" ("bla, " "blub, "))
案例1的输出应如下所示:
("val1" "val2" "val3")
问题在于,对于案例2,该函数当前正在正常工作(除了此sscce中的格式化问题),但不适用于案例1.对于案例1,它仅打印出键的第一个字母。我认为这是因为它在检查条件后会跳转到else块,但我不知道如何找到一个更好的条件来解决我的问题。
感谢您的帮助。
答案 0 :(得分:1)
简化此操作的一种好方法是使用multimethod。根据实际数据的表示方式,您的多方法调度功能可以像在输入上调用type
一样简单,可能的调度值类似于clojure.lang.PersistentArrayMap
和clojure.lang.PersistentVector
。更安全的调度方法将允许使用其他类型的顺序集合(例如列表和Java数组)以及其他类型的关联集合(例如有序映射)。你可以这样做:
(defmulti foo (juxt map? sequential?))
(defmethod foo [true false] ; input is a map of some sort
[val]
(mapcat (fn [[k vs]] [k (apply str (interpose ", " vs))]) val))
(defmethod foo [false true] ; input is a list, vector, etc.
[val]
(apply str (interpose ", " val)))
(foo {"Produkt" ["bla" "blub"] "Test" ["12" "34" "45"]})
;=> ("Produkt" "bla, blub" "Test" "12, 34, 45")
(foo ["val1" "val2" "val3"])
;=> "val1, val2, val3"
这些并不完全是您在问题中给出的预期输出,因为对我来说有点令人困惑的是您的代码正在尝试完成什么,但希望这至少说明了如何为不同的代码调度不同的代码使用multimethods可以轻松完成参数类型。
答案 1 :(得分:0)
我自己发现了它:
我用过:
(if-not (some vector? val)
...
)
而不是其他条件。现在它有效。