Haskell迭代超过2d列表,过滤,输出1d列表

Ken*_*son 16 haskell

我以为我在Haskell研究中一帆风顺,直到......

我有一个[[Int]]

tiles = [[1,0,0]
        ,[0,1,0]
        ,[0,1,0]
        ]
Run Code Online (Sandbox Code Playgroud)

和数据类型:

data Coord = Coord
    { x :: Int
    , y :: Int 
    } deriving (Eq)
Run Code Online (Sandbox Code Playgroud)

基于输入tiles,我一直在尝试输出a [Coord],这样Coord只有当值为tiles1 时才生成a ,并且Coord它将在2d列表中存储它的位置:

blackBox :: [[Int]] -> [Coord]
blackBox tiles = <magic> 
-- given the above example I would expect:
-- [(Coord 0 0),(Coord 1 1),(Coord 1 2)]
Run Code Online (Sandbox Code Playgroud)

我尝试过第一次将[[Int]]转换为[Int],通过:

foldTiles :: [[Int]] -> [Int]
foldTiles tiles = foldr (++) [] tiles
Run Code Online (Sandbox Code Playgroud)

但在那之后,我不确定如何传递指数.我想如果我可以映射"折叠的瓷砖",输出一个元组(值,索引),我可以很容易地找出其余部分.

更新如果有人感兴趣,我得到它的工作,这里是它的演示(源代码和GitHub的链接)!我将不得不花更多的时间来理解每个答案,因为这是我第一次使用FP编写游戏.非常感谢!

http://kennycason.com/posts/2013-10-10-haskell-sdl-gameboy-boxxle.html

kqr*_*kqr 12

这是列表理解发光的地方.

blackBox tiles =
  [Coord x y                         -- generate a Coord pair
    | (y, row) <- enumerate tiles    -- for each row with its coordinate
    , (x, tile) <- enumerate row     -- for each tile in the row (with coordinate)
    , tile == 1]                     -- if the tile is 1
Run Code Online (Sandbox Code Playgroud)

或者您可以使用等效do符号(因为列表是monad),这需要导入Control.Monad(for guard.)

blackBox tiles = do
  (y, row) <- enumerate tiles    -- for each row with its coordinate
  (x, tile) <- enumerate row     -- for each tile in the row (with coordinate)
  guard $ tile == 1              -- as long as the tile is 1
  return $ Coord x y             -- return a coord pair
Run Code Online (Sandbox Code Playgroud)

为了帮助理解,后一个函数的工作方式类似于以下Python函数.

def black_box(tiles):
    for y, row in enumerate(tiles):
        for x, tile in enumerate(row):
            if tile == 1:
                 yield Coord(x, y)
Run Code Online (Sandbox Code Playgroud)

do 列表monad的表示法对于处理列表非常方便,我认为,所以值得环顾四周!


在这两个例子中,我都使用了这个定义

enumerate = zip [0..]
Run Code Online (Sandbox Code Playgroud)