2012-06-19 19 views
6

Vorrei iterare su una collezione e al contempo mantenere un contatore exImplementare un contatore a

(for [x (range 10) y (inc 0)] [x y]) 

Vorrei 'y' per rappresentare il contatore, quindi per ogni elemento dell'uscita è ([0 0] [1 1] [2 2] ...). Come lo faccio?

risposta

12

È possibile utilizzare indexed da clojure.contrib.seq. Esempio:

(indexed '(a b c d)) => ([0 a] [1 b] [2 c] [3 d]) 

È inoltre possibile utilizzare map-indexed. Esempio:

(map-indexed vector "foobar") => ([0 \f] [1 \o] [2 \o] [3 \b] [4 \a] [5 \r]) 
6

Utilizzare map-indexed come consigli Simeon. Nel for contesto è comodo da usare destrutturazione per avere un facile accesso sia al banco e gli elementi della collezione:

(for [ [y x] (map-indexed vector (range 10)) ] [x y]) 

> ([0 0] [1 1] [2 2] [3 3] [4 4] [5 5] [6 6] [7 7] [8 8] [9 9]) 
1
(keep-indexed (fn [i el][el i]) (range 10)) 

o

(keep-indexed #(vec [%2 %1]) (range 10)) 
(keep-indexed #(identity [%2 %1]) (range 10)) 
;([0 0] [1 1] [2 2] [3 3] [4 4] [5 5] [6 6] [7 7] [8 8] [9 9]) 
1

Inoltre, ricorda che utilizzando gli indici in Clojure è generalmente un odore di codice.

2

Immagino che se questa domanda non fosse ancora stata contrassegnata come "risposta", potrebbe esserci qualcos'altro che stai cercando, e forse è la flessibilità di definire il tuo contatore.

Sono d'accordo con gli altri che per il problema specifico delineato, map-indexed è la strada da percorrere. Tuttavia, se ti ostini a usare for, mi sento di raccomandare qualcosa di simile:

(for [[x y] (map vector (range 10) (iterate inc 0))] 
    [x y]) 

Rafal ha una risposta molto simile, se non che il contatore sempre iniziare da zero e l'incremento di 1. Nella mia versione si potrebbe definire il tuo contatore come meglio credi. Ad esempio, modificando il precedente (iterate inc 0) a (iterate #(+ 2 %) 10), si potrebbe invece avere un contatore che inizia a 10 e incrementi di 2.

Problemi correlati