/ / Clojure - działa na każdym elemencie na liście list - lista, clojure, programowanie funkcjonalne, wartość zwracana

Clojure - działają na każdej pozycji na liście list - lista, clojure, funkcjonalne programowanie, wartość zwracana

Pracuję nad moim pierwszym programem funkcjonalnymw Clojure. Mam problemy z ustaleniem, jak przejść przez każdy element na liście, na każdej liście na liście i operować nim, zachowując wartości zwracane. Jestem pewien, że problem wynika z mojej nieznajomości Clojure i programowania funkcjonalnego oraz miał nadzieję, że ktoś wyjaśni najlepszą metodę wykonania następujących czynności:

psuedo-code algorithm:
for each lst in list
for each item in lst
return_values.append = do_something(item)

Najpierw próbowałem zagnieździć dwa doseq funkcje, a następnie wywoływanie mojego do_something funkcja, która działała, aby wywołać funkcję na elemencie, ale nie zapisała moich wartości zwracanych. Następnie spróbowałem for i cons do pustej listy, ale nie udało mi się uzyskać wartości zwracanych poza for.

Czy byłoby możliwe / najlepiej najpierw rozbić listę list? Czy nadal mogę uzyskać listę list wartości zwracanych?

Na koniec chciałbym, aby wynik był listąlist wartości zwracanych, aby pasowały do ​​wejściowej listy list. Gdyby ktoś mógł wyjaśnić najlepszą metodę zrobienia tego w Clojure i dlaczego, byłby bardzo wdzięczny.

Odpowiedzi:

5 dla odpowiedzi № 1

Zagnieżdżony for Pętla załatwi sprawę:

(for [lst my-list]
(for [item lst] (do_something item)))

Zajmie listę zagnieżdżoną my-list (lista list) i przekonwertuj ją na inną listę zagnieżdżoną, stosując do_something do każdego elementu.

W clojure for zwraca już listę wartości, więc nie matrzeba sobie z tym poradzić. Ponadto, ponieważ wszystkie struktury danych w clojure są niezmienne, nie można tego zrobić, dodając elementy do początkowo pustej listy za pomocą cons.


0 dla odpowiedzi nr 2

Jeśli masz głęboko zagnieżdżoną listę i chcesz zachować jej strukturę, ale przekształcić wartości, możesz użyć clojure.walk/postwalk do obsługi każdej wartości, np .:

(def nested "(1 (2 3 (4 5)) 6))

(defn transform-values [coll f]
(clojure.walk/postwalk #(if (not (list? %))
(f %)
%)
coll))

(transform-values nested inc)

=> (2 (3 4 (5 6)) 7)

Możesz oczywiście przekazać dowolną funkcję transform-values.


0 dla odpowiedzi № 3

Można to zrobić jako zwykły marsz rekurencyjny. Pierwszą implementacją, która przychodzi na myśl, będzie następująca sekwencja:

(defn deep-walk
[f data]
(map (fn [s] (if (seq? s)
(deep-walk f s)
(f s)))
data))

I ta niewielka zmiana dla wektorów:

(defn vec-deep-walk
[f data]
(vec (map (fn [s] (if (vector? s)
(vec-deep-walk f s)
(f s)))
data)))

Szybki test z następującymi elementami:

(vec-deep-walk (partial + 1) [1 [2 3] 4 [5 [6 7]]])

Daje następujące dane wyjściowe:

[2 [3 4] 5 [6 [7 8]]]

Funkcje marszu mają dwa parametry, pierwszyto funkcja, która przyjmuje pojedynczy parametr. Zostanie to wywołane dla każdego elementu nie będącego sekwencją / w danych, który jest przekazywany jako drugi parametr. Wyniki zostaną zwrócone w zagnieżdżonej strukturze, która jest identyczna ze strukturą wejściową.