Есть ли стандартное имя для этой операции?
Поэтому, работая над проектом на Haskell, я написал следующую функцию:
reGrid :: [[[a]]] -> [[a]]
reGrid [] = []
reGrid xs | any null xs = []
| otherwise = (concat $ map head xs) : reGrid (map tail xs)
Для тех, кто не говорит на Хаскеле, это берет список матриц и объединяет соответствующие строки в новую матрицу.
В этом проекте он несколько раз появлялся, и я чувствую, что это какая-то обычная операция, которую я пропустил.
Есть ли стандартное имя для этой операции? Поиск в Google для
[[[a]]] -> [[a]
Ничего полезного не дает.
2 ответа
У вас есть куча вещей, и вы хотите превратить их в одну вещь. Обычный способ сделать это с какой-то складкой. Итак, начнем с этого:
regrid [] = []
regrid xs = foldr go (repeat []) xs
Теперь предположим, что у вас есть одна матрица, и у вас также есть результат изменения сетки остальных. Как вы можете их объединить? Ну, вы хотите объединить строки, пока не закончится, что звучит как работа для zipWith
, Итак, все вместе,
regrid = foldr (zipWith (++)) []
Это не одна стандартная функция, но она короткая и не обходится без частичных функций. Однако у него есть проблема эффективности, если список длинный. Чтобы это исправить, вы можете переключиться на левый фолд, но получить правильную строгость будет непросто. Я могу написать это позже.
Ваша функция очень похожа (но не идентична) на эту:
reGrid' = map concat . transpose
Например, мое свойство QuickCheck \xs -> reGrid xs == reGrid' xs
поднимает эту разницу:
*Main> reGrid [[[]],[]]
[]
*Main> reGrid' [[[]],[]]
[[]]
Короче говоря, ваша версия "обрежет" больше вещей, которые могут вас волновать (или нет). Для более наглядного примера:
*Main> reGrid [["abc"],[]]
[]
*Main> reGrid' [["abc"],[]]
["abc"]
Вы можете судить сами, имеют ли значение случаи, когда они отличаются.