如何遍历列表列表

时间:2019-08-26 16:26:16

标签: list haskell

我有一个列表列表,例如

[[1, 1, 1, 1], 
 [0, 0, 0, 0], 
 [1, 1, 0, 0], 
 [0, 0, 1, 1]] 

长度均匀。像黑色象素棋盘一样,黑色为1,白色为0的像素正方形。

我想要一个将返回4个列表的函数:

  • 第一个列表在右下角2x2处将是[1,1,0,0]的列表
  • 第二个列表是右上角2x2的列表,其中包含[1,1,0,0]
  • 第三个列表是左下角2x2的列表,其中包含[0,0,1,1]
  • 第四个列表在左上角2x2处将是带有[1,1,0,0]的列表

我还不太知道该怎么做。我希望收到上述4个列表。

1 个答案:

答案 0 :(得分:3)

假设我现在已经了解您的要求,那么以下内容对我有用。可能有更复杂的方法来执行此操作,但这是一个简单的方法,并不太麻烦-关键是编写通用函数,该函数可以使用偶数长度列表的前一半/后一半。然后,您可以轻松地从中构建所需的功能:

firstHalf :: [a] -> [a]
firstHalf xs
    | odd n = error "list needs to have even length"
    | otherwise = take h xs
    where n = length xs
          h = n `div` 2

secondHalf :: [a] -> [a]
secondHalf xs
    | odd n = error "list needs to have even length"
    | otherwise = drop h xs
    where n = length xs
          h = n `div` 2

topLeftCorner :: [[a]] -> [a]
topLeftCorner = concatMap firstHalf . firstHalf

topRightCorner :: [[a]] -> [a]
topRightCorner = concatMap secondHalf . firstHalf

bottomLeftCorner :: [[a]] -> [a]
bottomLeftCorner = concat . reverse . map firstHalf . secondHalf

bottomRightCorner :: [[a]] -> [a]
bottomRightCorner = concat . reverse . map secondHalf . secondHalf

allCorners :: [[a]] -> [[a]]
allCorners board = [bottomRightCorner, topRightCorner, bottomLeftCorner, topLeftCorner] <*> [board]

使用它的示例,首先是您的输入,然后是一个6x6的示例:

*Main>let board = [[1,1,1,1], [0,0,0,0], [1 ,1, 0,0] , [0, 0, 1,1]]                                              
*Main> allCorners board
[[1,1,0,0],[1,1,0,0],[0,0,1,1],[1,1,0,0]]
*Main> let board = [[1,1,1,1,1,1], [0,0,0,0,0,0], [1 ,1, 0,0,1,1] , [0, 0, 1,1,0,0], [1,1,1,1,1,1], [0,0,0,0,0,0]]
*Main>allCorners board                                                                                           
[[0,0,0,1,1,1,1,0,0],[1,1,1,0,0,0,0,1,1],[0,0,0,1,1,1,0,0,1],[1,1,1,0,0,0,1,1,0]]

在函数式程序设计中(实际上甚至在一般的程序设计中),解决一个更复杂问题的最佳方法是将其分解为较小的问题。