В Clojure я хочу объединить два списка, чтобы получить список пар,
> (zip '(1 2 3) '(4 5 6))
((1 4) (2 5) (3 6))
В Haskell или Ruby функция называется zip . Реализовать это несложно, но я хотел убедиться, что не пропустил ни одной функции в Core или Contrib.
Есть молния Core пространство имен , но оно описано как обеспечивающее доступ к функциональной технике Zipper, которая, похоже, не то, что мне нужно.
Есть ли в Core эквивалентная функция для объединения 2 или более списков таким образом?
Если нет, то это потому, что существует идиоматический подход, который делает функцию ненужной?
zip
библиотеке Tupelo есть функция: cloojure.github.io/doc/tupelo/tupelo.core.html#var-zipОтветы:
делает то, что вы хотите:
Haskell необходим набор
zipWith
(zipWith3
,zipWith4
, ...) функции, потому что они все должны быть определенного типа ; в частности, необходимо зафиксировать количество принимаемых списков ввода. (Thezip
,zip2
,zip3
... семья может рассматриваться как специализацияzipWith
семьи для общего пользования случае кортежей).Напротив, Clojure и другие Lisp хорошо поддерживают функции переменной арности;
map
является одним из них и может использоваться для "кортежа" аналогично Haskell'sИдиоматический способ создания «кортежа» в Clojure - это построить короткий вектор, как показано выше.
(Для полноты картины обратите внимание, что Haskell с некоторыми базовыми расширениями действительно допускает функции переменной арности; однако их использование требует хорошего понимания языка, а ванильный Haskell 98, вероятно, не поддерживает их вообще, поэтому функции с фиксированной арностью предпочтительнее для стандартной библиотеки.)
источник
zip
когда коллекции имеют разную длину. Ruby продолжит обработку и предоставитnil
s для более короткой коллекции, тогда как Clojure прекратит обработку, как только одна из коллекций будет исчерпана.zip
ведет себя как Clojuremap
.или в более общем смысле
источник
источник
чтобы дать вам именно то, что вы хотели, сопоставление
list
двух списков даст вам список списков, как в вашем примере. Я думаю, что многие клоджурцы склонны использовать для этого векторы, хотя это будет работать с чем угодно. и входы не обязательно должны быть одного типа. map создает из них последовательности, а затем сопоставляет их, поэтому любой ввод с последовательностью будет работать нормально.источник
Встроенный способ - это просто функция interleave:
источник
(partition 2 (interleave [1 2 3 4][5 6 7 8]))
Существует функция под названием zipmap, которая может иметь аналогичный эффект (zipmap
(1 2 3)
(4 5 6)). Вывод выглядит следующим образом: {3 6, 2 5, 1 4}источник
# (применить список карт%) транспонирует матрицу точно так же, как функция Python zip *. Как определение макроса:
user => (defmacro py-zip [lst] `(применить список карт ~ lst))
# 'Пользователь / ая-молния
user => (py-zip '((1 2 3 4) (9 9 9 9) (5 6 7 8)))
((1 9 5) (2 9 6) (3 9 7) (4 9 8))
user => (py-zip '((1 9 5) (2 9 6) (3 9 7) (4 9 8)))
((1 2 3 4) (9 9 9 9) (5 6 7 8))
источник