输入:“Michael”“Julia”“Joe”“Sam”
输出:嗨,迈克尔,朱莉娅,乔和萨姆。 (注意逗号和“和”这个词)
输入:nil
输出:嗨,世界。
这是我的第一次尝试:
(defn say-hi [& name]
(print "Hi," name))
user> (say-hi "Michael")
Hi, (Michael)
nil
user> (say-hi "Michael" "Julia")
Hi, (Michael Julia)
nil
问题:
如何实现默认:(无输入,说“Hi World!”)
如何摆脱输出中名字周围的父母?
如何实现逗号分隔并添加连词“和”?
答案 0 :(得分:1)
首先,Clojure支持多个arity函数,所以你可以做这样的事情来实现默认行为:
(defn say-hi
([] (say-hi "World"))
([& names] ...))
然后,您想要的是使用seq并将它们包含的所有字符串连接在一起,在它们之间使用", "
。 clojure.string
命名空间包含许多字符串操作函数,其中一个是clojure.string/join
:
(require '[clojure.string :as string])
(string/join ", " ["Michael", "Julia"])
;; => "Michael, Julia"
但是seq的最后一个元素应该使用" and "
作为分隔符连接起来,所以你最终会得到这样的结果:
(require '[clojure.string :as string])
(defn say-hi
([] (say-hi "World"))
([& names]
(if (next names)
(format "Hi, %s, and %s!"
(string/join ", " (butlast names))
(last names))
(format "Hi, %s!" (first names)))))
请注意,您必须区分单名称和多名称案例,(next names)
基本上检查seq是否包含多个元素。 (您可以通过向函数添加另一个arity来实现相同的目标。)
(say-hi)
;; => "Hi, World!"
(say-hi "Michael")
;; => "Hi, Michael!"
(say-hi "Michael" "Julia" "Joe" "Sam")
;; => "Hi, Michael, Julia, Joe, and Sam!"
答案 1 :(得分:0)
您可以使用clojure.string/join
:
(use '[clojure.string :only [join]])
(defn sentencify [& elems]
(->>
[(join ", " (butlast elems)) (last elems)]
(remove empty?)
(join " and ")))
(defn say-hi [& name]
(print "Hi," (if name
(sentencify name)
"World!")))
答案 2 :(得分:0)
简明的解决方案:
(defn say-hi [& names]
(let [names (case (count names)
0 ["world"]
1 names
(concat (butlast names) (list (str "and " (last names)))))]
(->> names, (cons "Hi"), (interpose ", "), (apply str))))
(say-hi)
;"Hi, world"
(say-hi "Michael")
;"Hi, Michael"
(say-hi "Michael" "Julia" "Joe" "Sam")
;"Hi, Michael, Julia, Joe, and Sam"
对于names
的长列表,您可能希望避开count
,last
和butlast
,可能首先将names
倾注到向量中。
要打印(如问题所示)而不是返回格式化字符串,请将print
附加到最终表单:
(->> names, (cons "Hi"), (interpose ", "), (apply str), print)