如何从Clojure中的列表中复制项目?

时间:2015-07-07 23:36:07

标签: list clojure

我已经尝试了这么多晚,我终于放弃了自己。看起来像一个非常简单的问题,但我想我并不完全理解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))
)

但这只是给了我一个例外。我已经尝试了很多其他的解决方案,这可能不是我最好的解决方案之一,但这是我能在这里发布一些最快的方法。

4 个答案:

答案 0 :(得分:3)

(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

答案 1 :(得分: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)

请注意,repeatfor都是惰性函数,除非我真的需要它,否则我宁愿避免使用它们。此外,我通常更喜欢将我的线性集合存储在具体的矢量中,而不是通用的“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]

答案 2 :(得分:1)

我建议建立在Alan的解决方案上,而不是使用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)

答案 3 :(得分:0)

(reduce #(count (map println (repeat %1 %2))) num list)