Правильная форма для использования 2D-массива в Clojure и инициализации каждой ячейки - PullRequest
5 голосов
/ 03 марта 2011

(начинающий Лисп) Мне нужно создать 2D-массив и инициализировать каждую ячейку в массиве. Каждая ячейка инициализируется функцией, основанной на данных в предыдущей ячейке. Таким образом, ячейка как 0,1 будет инициализирована с результатом функции, которая использует данные из ячейки 0,0, и так далее.

Мне было интересно, какова правильная идиома clojure для настройки такой структуры данных.

Ответы [ 2 ]

11 голосов
/ 03 марта 2011

Представление вашего массива на самом деле зависит от необходимости его использования, а не инициализации.Например, если у вас плотная матрица, вам, скорее всего, следует использовать вектор таких векторов:

[[0, 1, 2, 3, 4],
 [5, 6, 7, 8, 9],
 [9, 8, 7, 6, 5],
 [4, 3, 2, 1, 0],
 [0, 1, 2, 3, 4]]

или один вектор с дополнительной информацией о необработанной длине:

{:length 5
 :data
 [0, 1, 2, 3, 4, 
 5, 6, 7, 8, 9,
 9, 8, 7, 6, 5, 
 4, 3, 2, 1, 0, 
 0, 1, 2, 3, 4]
}

иесли вам нужна разреженная матрица, вы можете использовать hash-map s:

{0 {0 0, 4 4},
 2 {2 7},
 3 {0 4, 2 2}}

(поскольку ваш 2D-массив мал и вы генерируете следующее значение на основе предыдущего, я считаю, что первый вариант лучше подходит для вас),

Если вы собираетесь выполнять множество специфических для матрицы манипуляций (умножение, декомпозиция и т. Д.), Вы можете использовать некоторые существующие библиотеки, такие как Incanter .

А что касается заполнения, я предлагаю использовать переходные процессы и сохранять промежуточные результаты, т.е. (для одномерного вектора):

(defn make-array [initial-value f length]
  (loop [result (transient []), length-left length, interim-value initial-value]
    (if (= length-left 0)
        (persistent! result)
        (recur (conj! result (f interim-value)) (- length-left 1) (f interim-value))))

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

2 голосов
/ 04 марта 2011

Я не знаю, является ли это плохой техникой, но я использовал хеш (или обычно упорядоченные) карты, чтобы указать 2D "массивы". Они накапливаются так:

{ [x y] value ... }

Есть минусы в этом, так как вы должны как-то указать пределы массива. И, вероятно, это очень медленно по сравнению с прямыми векторными презентациями, как описано в сообщении друга.

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