为了计划晚餐菜单,用户希望轮换3天肉,然后一个素食主菜。肉类轮换是牛肉,鸡肉,鱼肉,猪肉。蔬菜旋转搅拌然后豆腐。是否有比我下面的更好(更优雅,更简洁或可读)的方式来生成膳食序列?
(defn menu [n] (let [meat (cycle '[:beef :chicken :fish :pork])
veg (cycle '[:stirfry :tofu])]
(take n (mapcat seq (interleave (partition 3 meat) (partition 1 veg))))))
答案 0 :(得分:1)
这个更短,更容易阅读我猜(并且可能更快):
(defn menu [n]
(let [meat (cycle '[:beef :chicken :fish :pork])
veg (cycle '[:stirfry :tofu])]
(take n (rest (mapcat conj (partition 3 meat) veg)))))
在repl中:
user> (menu 10)
(:beef :chicken :fish :tofu :pork :beef :chicken :stirfry :fish :pork)
因为mapcat
可以进行多次收集,所以会做
(conj (:beef :chicken :fish) :stirfry)
(conj (:pork :beef :chicken) :tofu)
依此类推
你只需要删除第一个值,因为带有列表的conj
会在开头添加一个元素。
如果可以从蔬菜餐开始,那么您也可能会丢失rest
,使其缩短。
(take n (mapcat conj (partition 3 meat) veg))
答案 1 :(得分:0)
我很想概括这个问题:
您可以提供数据作为备用数量和序列的菜肴。对于你的例子,我们有
(def dishes [3 [:beef :chicken :fish :pork]
1 [:stirfry :tofu]])
我们可以调整您的解决方案,以产生无尽的懒惰菜肴序列:
(defn rotate [nlist-pairs]
(let [pairs (partition 2 nlist-pairs)
sources (map (fn [[n xs]] (partition n (cycle xs)))
pairs)]
(apply concat (apply interleave sources))))
获得前十名......
(take 10 (rotate dishes))
;(:beef :chicken :fish :stirfry :pork :beef :chicken :tofu :fish :pork)