我已经尝试了很多个夜晚,最终我放弃了自己。似乎是一个非常简单的问题,但我想我只是没有完全理解 Clojure (我部分地将其归因于我几乎唯一的命令式语言经验)。问题来自 hackerrank.com
问题来了:
Problem Statement
Given a list repeat each element of the list n times. The input and output
portions will be handled automatically by the grader.
Input Format
First line has integer S where S is the number of times you need to repeat
elements. After this there are X lines, each containing an integer. These are the
X elements of the array.
Output Format
Repeat each element of the original list S times. So you have to return
list/vector/array of S*X integers. The relative positions of the values should be
same as the original list provided as input.
Constraints
0<=X<=10
1<=S<=100
所以,鉴于:
2
1
2
3
输出:
1
1
2
2
3
3
我已经尝试过:
(fn list-replicate [num list]
(println (reduce
(fn [element seq] (dotimes [n num] (conj seq element)))
[]
list))
)
但这只是给了我一个例外。我已经尝试了很多其他解决方案,这可能不是我更好的解决方案之一,但它是我能想到的在此处发布内容的最快解决方案。
(defn list-replicate [num list]
(mapcat (partial repeat num) list))
(doseq [x (list-replicate 2 [1 2 3])]
(println x))
;; output:
1
1
2
2
3
3
前面的答案很短,也有效,但是很“压缩”,对于新人来说不容易学习。我会用一种更简单、更明显的方式来做。
首先看
repeat
函数:
user=> (doc repeat)
-------------------------
clojure.core/repeat
([x] [n x])
Returns a lazy (infinite!, or length n if supplied) sequence of xs.
user=> (repeat 3 5)
(5 5 5)
所以我们看到如何轻松地重复某件事 N 次。
如果我们对列表的每个元素运行(重复 n ...)会怎样?
(def N 2)
(def xvals [1 2 3] )
(for [curr-x xvals]
(repeat N curr-x))
;=> ((1 1) (2 2) (3 3))
我们已经很接近了,但是我们有一个用于输出的列表列表。怎么修?最简单的方法是使用
flatten
函数:
(flatten
(for [curr-x xvals]
(repeat N curr-x)))
;=> (1 1 2 2 3 3)
请注意,
repeat
和for
都是惰性函数,除非我真的需要它们,否则我宁愿避免它们。另外,我通常更喜欢将线性集合存储在具体的向量中,而不是通用的“seq”类型。由于这些原因,我添加了一个额外步骤,将结果强制转换为最终产品的单个(eagar)向量:
(defn list-replicate [num-rep orig-list]
(into []
(flatten
(for [curr-elem xvals]
(repeat N curr-elem)))))
(list-replicate N xvals)
;=> [1 1 2 2 3 3]
我建议构建艾伦的解决方案,而不是使用 concat 进行扁平化,因为这将保留数据的结构,以防您输入像这样的 [[1 2] [3 4]]。
((fn [coll] (apply concat (for [x coll] (repeat 2 x)))) [[1 2] [3 4]])
output: => ([1 2] [1 2] [3 4] [3 4])
与展平不同,它执行以下操作
((fn [coll] (flatten (for [x coll] (repeat 2 x)))) [[1 2] [3 4]])
output: => (1 2 1 2 3 4 3 4)
对于简单的列表,例如'(1 2 3),效果是一样的:
((fn [coll] (apply concat (for [x coll] (repeat 2 x)))) '(1 2 3))
output => (1 1 2 2 3 3)
(reduce #(count (map println (repeat %1 %2))) num list)
(fn [num lst] (for [e lst _ (range num)] (println e)))
与 lambda 相同:
#(for [e %2 _ (range %)] (println e))