简体   繁体   English

在 Clojure 中将对象包装到集合中的惯用方法(如果它不是一个集合)?

[英]Idiomatic way to wrap object into collection (if it's not a collection already) in Clojure?

I have (for instance) a mix of data structures such as {:name "Peter" :children "Mark"} and {:name "Mark" :children ["Julia" "John"] ie :children value is either a single string or a collection of strings.我有(例如)混合数据结构,例如{:name "Peter" :children "Mark"}{:name "Mark" :children ["Julia" "John"]即 :children 值是单个字符串或字符串的集合。 Other functions in my code expect that the value of :children is always a collection of strings, so I need to adapt the data for them.我的代码中的其他函数期望 :children 的值始终是字符串的集合,因此我需要为它们调整数据。
Of course I can use something like:当然,我可以使用类似的东西:

(defn data-adapter [m]
  (let [children (:children m)]
    (assoc m :children 
             (if (coll? children) 
               children
               [children]))))

But is there a more idiomatic/laconic way?但是有没有更惯用/简洁的方式?

I think you will have to take no for an answer.我想你将不得不接受否定的答案。

(if (coll? x) x [x]) is about as terse and expressive as it gets. (if (coll? x) x [x])尽可能简洁和富有表现力。 It's what people usually use for this problem (sometimes with sequential? instead of coll? ).这是人们通常用于解决此问题的方法(有时使用sequential?而不是coll? )。

cond-> enthusiasts like me sometimes try to use it in place of a simple conditional, but here it is no improvement: cond->像我这样的爱好者有时会尝试使用它来代替简单的条件,但这里没有改进:

(cond-> x (not (coll? x)) vector)

In the context of your code, however, you can do a little better.但是,在您的代码上下文中,您可以做得更好一些。 A lookup and association is best expressed with update :查找和关联最好用update表示:

(defn data-adapter [m]
  (update m :children #(if (coll? %) % [%])))

the only advice would be to abstract that logic to some function, to keep your actual business logic clean.唯一的建议是将该逻辑抽象为某个函数,以保持您的实际业务逻辑清晰。

(defn data-adapter [m]
  (let [children (:children m)]
    (assoc m :children (ensure-coll children))))   

or, more concise, with update :或者,更简洁,使用update

(defn data-adapter [m]
  (update m :children ensure-coll))

where ensure-coll could be something like this:其中ensure-coll可能是这样的:

(defn iffun [check & {:keys [t f] :or {t identity f identity}}]
  #((if (check %) t f) %))

(def ensure-coll (iffun coll? :f list))

(or whatever another implementation you like) (或您喜欢的任何其他实现)

user> (data-adapter {:children 1})
;;=> {:children (1)}

user> (data-adapter {:children [1]})
;;=> {:children [1]}

Perhaps not idiomatic, but laconic:也许不习惯,但简洁:

(flatten [x])

https://clojuredocs.org/clojure.core/flatten https://clojuredocs.org/clojure.core/flatten

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Clojure:包装集合中每个元素的惯用方式 - Clojure: Idiomatic way to wrap each element in collection 是否有更惯用的方法来获取Clojure中的N个随机元素? - Is there a more idiomatic way to get N random elements of a collection in Clojure? 在Clojure中迭代所有对集合的惯用方法 - Idiomatic way to iterate through all pairs of a collection in Clojure 将这个clojure片段用字符串写入concat集合的惯用方法是什么? - what is the idiomatic way to write this clojure snippet to concat collection with a string? 删除具有包含一个或多个给定单词集合的值的集合元素的最惯用的方法是什么? - What's the most idiomatic way to to remove collection elements with values containing one or more of a given collection of words? 写这篇文章最恰当的Clojure方式是什么? - What's the most idiomatic Clojure way to write this? Clojure-idiomatic初始化Java对象的方法 - Clojure-idiomatic way to initialize a Java object 习惯性Clojure模仿Python的收益率的方式 - Idiomatic Clojure way of mimicking Python's yield 返回集合中的下一个成员的惯用方式是什么? - What is the idiomatic way of returning the next member in collection? 如何对Clojure中已经分组的集合进行分组? - How to group-by a collection that is already grouped by in Clojure?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM