2014-04-08 18 views
5

Próbuję wygenerować wszystkie możliwe prefiksowe podciągi danego łańcucha w clojure. Na przykład, jeśli słowo jest Ninja chcę wyjście być ("N" "Ni" "Nin" "Ninj" "Ninja")Generowanie podciągów w clojure

można łatwo zrobić z tym:

user=> (def a "Ninja") 

user => (for [x (range 1 (+ 1 (.length a)))] 
      (subs a 0 x)) 

("N" "Ni" "Nin" "Ninj" "Ninja") 

I to wszystko jest w porządku ... chyba .. Używam dla pętli w tym miejscu .. i nie wygląda to tak bardzo clojure-y .. czy istnieje lepszy/właściwy sposób na zrobienie tego bez pętli for lub czy pętla for całkowicie okay się w tym przypadku?

dziękuję

+0

być jasne, 'for' w Clojure nie pętli for jest to lista zrozumienie – noisesmith

Odpowiedz

4

Mapowanie subs na długości jak w for zrozumieniem lub with map explicitly to co zrobię, jak również.

Jeśli jednak naprawdę chcą funkcji wyższego poziomu, można użyć reductions

(rest (reductions str (str) "Ninja")) 
;=> ("N" "Ni" "Nin" "Ninj" "Ninja") 

Gdybyś chciał przyrostków zamiast, można zrobić tak ładnie z iterate i subs ponieważ nie miałoby określić koniec.

(take-while seq (iterate #(subs % 1) "Ninja")) 
;=> ("Ninja" "inja" "nja" "ja" "a") 
+0

nie wiedział o tej funkcji - http://clojuredocs.org/clojure_core/clojure.core/reductions – Scott

+0

obniżki są całkiem fajne, dzięki! Również dziękuję za uwagi na temat 'for', myślę, że dla czytelnika może być o wiele bardziej oczywiste, co robi, niż redukcje. – LocustHorde

4

for Ułatwienia są perfekcyjnie, IMO. Jeśli chcesz zobaczyć inne podejście, tutaj jest to, co chciałbym zrobić:

(map (partial subs a 0) (range 1 (-> a count inc))) 
;; ("N" "Ni" "Nin" "Ninj" "Ninja") 
+0

Zamiast' (powtórzyć) ', tylko miejsce 'a' jako pierwszy argument do' subs'. –

+0

@ A.Web niezła sugestia. Teraz to już prawie Twoja odpowiedź :) – Kyle

+1

Tak, dlatego usunąłem moje :). –

1

Można użyć reduce

user=> (reduce #(conj % (str (first %) %2)) '() "Ninja") 
("Ninja" "Ninj" "Nin" "Ni" "N")