Есть ли стандартное имя для этой операции?

Поэтому, работая над проектом на 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"]

Вы можете судить сами, имеют ли значение случаи, когда они отличаются.

Другие вопросы по тегам