Поворот матрицы списков в Clojure - PullRequest
10 голосов
/ 29 ноября 2011

Я новичок в Clojure и функциональном программировании в целом.Я в недоумении, как справиться с этим функционально.

У меня есть следующая матрица:

(def matrix [[\a \b \c]
             [\d \e \f]
             [\g \h \i]])

Я хочу преобразовать ее в нечто подобное (вращение против часовой стрелки):

((\a \d \g)
 (\b \e \h)
 (\c \f \i ))

Я взломал этот бит, который дает мне элементы в правильном порядке.Если бы я мог собрать данные в строку таким образом, я мог бы разделить их на разделы.Тем не менее, я почти уверен, что dosq - неправильный путь:

(doseq [i [0 1 2]]
  (doseq [row matrix]
    (println (get (vec row) i))))

Я баловался с вложенными вызовами карты, но продолжаю зацикливаться на этом.Как правильно построить строку в Clojure или обработать ее еще лучше?

Ответы [ 4 ]

32 голосов
/ 29 ноября 2011

То, что вы пытаетесь достичь, звучит как transpose . Я бы предложил

(apply map list matrix)
; => ((\a \d \g) (\b \e \h) (\c \f \i))

Что это делает?

(apply map list '((\a \b \c) (\d \e \f) (\g \h \i)))

эквивалентно

(map list '(\a \b \c) '(\d \e \f) '(\g \h \i))

, который берет первые элементы каждого из трех списков, список вызовов в них, затем берет вторые элементы, список вызовов в них ... An возвращает последовательность всех списков, которые были сгенерированы таким образом.

Еще пару примеров apply и map можно найти на ClojureDocs.

9 голосов
/ 29 ноября 2011

Взятие решения матричного транспонирования непосредственно из кода розетки:

(vec (apply map vector matrix))

Чтобы увидеть, что происходит, рассмотрите:Это будет хорошо работать с произвольными размерами матрицы, хотя это не подходит для значительного сокращения чисел, для этого вы можете рассмотреть возможность использования библиотеки манипулирования матрицей на основе Java из Clojure.

5 голосов
/ 16 марта 2014

Вы можете использовать core.matrix, чтобы очень легко выполнять подобные операции с матрицами.В частности, уже есть функция transpose, которая делает именно то, что вы хотите:

Пример:

(use 'clojure.core.matrix)

(def matrix [[\a \b \c]
             [\d \e \f]
             [\g \h \i]])

(transpose matrix)
=> [[\a \d \g] 
    [\b \e \h] 
    [\c \f \i]]
2 голосов
/ 29 ноября 2011

Вот один из способов:

(def transposed-matrix (apply map list matrix))
;=> ((\a \d \g) (\b \e \h) (\c \f \i))

(doseq [row transposed-matrix] 
  (doall (map println row)))

Это дает тот же результат, что и ваш оригинал (печать столбцов matrix).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...