假设我有一些像这样组织在网格中的数据(尺寸可能会有所不同,但网格的一侧始终是n**2
):
0 1 2 3
4 5 6 7
8 9 A B
C D E F
我想要实现的是拥有一个列表,其中包含以不同方式表示的相同数据,即分成列、行或(最重要的)单元格,即
0 1 | 2 3
4 5 | 6 7
----+----
8 9 | A B
C D | E F
因此,如果我执行一些操作,我将能够获取以下列表中的数据:
[[0, 1, 4, 5],
[2, 3, 6, 7],
[8, 9, C, D],
[A, B, E, F]]
在哪里订购无关紧要。
我想用它来构建一个镜头,它能够根据不同类型的表示来设置值。这可以通过在命令式语言中使用指针或引用来实现(如果适用)。
除了细节之外,我想知道是否有一种通用方法可以使相同的内部数据以不同的方式表示。
到目前为止,这是我得到的,[Int]
用作内部表示和转换函数来获取特定的“视图”:
import Data.List (transpose)
data Access = Rows | Columns | Cells
isqrt :: Int -> Int
isqrt = floor . sqrt . fromIntegral
group :: Int -> [a] -> [[a]]
group _ [] = []
group n l
| n > 0 = (take n l) : (group n (drop n l))
| otherwise = error "inappropriate n"
representAs :: [Int] -> Access -> [[Int]]
representAs list Rows = group (isqrt . length $ list) list
representAs list Columns = transpose $ list `representAs` Rows
representAs list Cells = let row_width = isqrt . length $ list
cell_width = isqrt row_width
drops = map (\x -> cell_width
* row_width
* (x `quot` cell_width)
+ cell_width
* (x `rem` cell_width)
) [0..row_width-1]
in (map ( (map snd)
. (filter ( (==0)
. (`quot` cell_width)
. (`rem` row_width)
. fst)
)
. (zip [0..])
. (take (row_width * cell_width))
. (`drop` list)
) drops
)
main = mapM_ (putStrLn . show) ([1..16] `representAs` Cells)
我的问题基于与此相同的想法,但那里的答案仅涉及内存问题,而不是构造问题。此外,如果我要在几个表示中以不同的方式存储相同的数据,据我所知,我将不得不更新所有这些数据以设置新值。