2010-04-23 19 views
6

Soy un novato en Clojure. Estoy tratando de obtener dos copias de un vector de cartas. La forma no DRY que puedo llegar a esRepetición de vectores en Clojure

(def suits [:clubs :diamonds :hearts :spades]) 
(def two-times (concat suits suits)) 

Tiene que haber una manera más funcional (incluso si se necesita más caracteres :-)). ¿Qué pasa si quiero N veces? ¿Alguna sugerencia?

Todas las cosas que trato, como

(replicate 2 suits) 

resultados en dos vectores separados:

([:clubs :diamonds :hearts :spades] [:clubs :diamonds :hearts :spades]) 

¿Cómo "aplanar" la estructura?

+1

No hay nada no funcional sobre el uso del valor de uno Var en el interior del 'def' forma de creación otro Var. De hecho, eso es lo que hay que hacer si el segundo Var depende de la primera. Por supuesto, si quiere un método general para concatenar n copias de un seq, donde n puede o no conocerse de antemano, entonces necesita una solución mejor (como se encuentra en las respuestas aquí). –

+1

En realidad, eso es lo que quise decir (N copias). Estoy de acuerdo en que mi función dos veces es "funcional", simplemente no es práctico si quiero 100 copias :-). – Ralph

Respuesta

7

concat le da una pereza ss. Si quieres acabar con un vector (no perezoso) en su lugar:

user> (into suits suits) 
[:clubs :diamonds :hearts :spades :clubs :diamonds :hearts :spades] 
user> (reduce into (replicate 2 suits)) 
[:clubs :diamonds :hearts :spades :clubs :diamonds :hearts :spades] 

Dependiendo de si está accediendo a este índice por mucho o interactuando sobre ella, ya sea un vector o una SEC podría ser más apropiado.

Siempre hay cycle también, si desea una corriente sin fin (perezoso) de elementos repetidos:

user> (take 9 (cycle suits)) 
(:clubs :diamonds :hearts :spades :clubs :diamonds :hearts :spades :clubs) 
+0

También se me ocurrió (tomar 8 (trajes de ciclo)). Parece que funciona, pero tuve que resolver la parte del "8" yo mismo, sin la ayuda de una computadora :-). – Ralph

2

(no probado!)

(apply concat (repeat 2 suits)) 

con suerte va a hacer el truco.

concat por supuesto concatenará 2 listas; apply se puede utilizar para pasar de contrabando una función dada a la posición principal de una lista existente para su evaluación.

+2

Se corrigió el nombre de la función ('assoc' ->' apply'). –

+0

Oh, qué estúpido de mí. Uso 'apply' todo el tiempo, creo que ya sabría su nombre ... ¡Gracias por la solución! –

+0

'(doc replica)' a partir de Clojure 1.7 dice 'DEPRECATED: Use 'repeat' en su lugar. –

2

Un poco de experimentación con el REPL me llevan a esta solución:

user=> (def suits [:clubs :diamonds :hearts :spades]) 
#'user/suits 
user=> suits 
[:clubs :diamonds :hearts :spades]  
user=> (reduce concat (replicate 2 suits)) 
(:clubs :diamonds :hearts :spades :clubs :diamonds :hearts :spades) 
1
(take (* 2 (count suits)) (cycle suits)) 
Cuestiones relacionadas