我有一个字符列表::[[Char]]
列表。
我需要遍历字符串列表以及每个字符串中的每个字符。
说,我的列表出现在这个变量中。
let xs
请建议一种简单的迭代方式。
答案 0 :(得分:15)
如果要将函数f
应用于列表的每个元素,请执行以下操作:
[a, b, c, d] → [f a, f b, f c, f d]
然后map f xs
就可以了。 map
将元素上的函数转换为列表上的函数。因此,我们可以将其嵌套以对列表列表进行操作:如果f
将a
转换为b
s,map (map f)
将[[a]]
转换为[[b]]
}}第
如果您想要为列表的每个元素执行一些IO操作(这更像传统迭代),那么您可能正在寻找forM_
: 1
forM_ :: [a] -> (a -> IO b) -> IO ()
你给它一个函数,它按顺序用列表的每个元素调用它。例如,forM_ xs putStrLn
是一个IO操作,它将在xs
中打印出自己行中的每个字符串。以下是forM_
:
main = do
...
forM_ xs $ \s -> do
putStrLn "Here's a string:"
forM_ s print
putStrLn "Now it's done."
如果xs
包含["hello", "world"]
,则会打印出来:
Here's a string:
'h'
'e'
'l'
'l'
'o'
Now it's done.
Here's a string:
'w'
'o'
'r'
'l'
'd'
Now it's done.
1 forM_
实际上有一个更通用的类型,但我所展示的更简单的版本在这里更相关。
答案 1 :(得分:3)
map (map f) l
其中f :: Char -> Foo
是适用于每个Char
和l :: [[Char]]
的函数
返回l' :: [[Foo]]
答案 2 :(得分:3)
迭代的“正确”方式实际上是 fold 。您可能想要对列表执行的任何操作都可以通过折叠完成。让我们考虑一下你想做什么。你可能会想到这样的事情:
for (row in xs):
for (c in row):
doSomething
问题是,你可能在doSomething
中使用了可变变量。没关系,我们可以解决这个问题。所以假设你有这个。
def iter2d(xs):
outerVar = outerInit
for (row in xs):
innerVar = innerInit(row)
outerVar.adjust1(row)
for (c in row):
innerVar.adjust2(c)
outerVar.adjust3(c, innerVar)
return outerVar
让我们把它翻译成折叠。和不变性。
iter2d :: [[Char]] -> Something
iter2d xs = foldl' outerStep outerInit xs
where outerInit = ... -- same as outerInit above
outerStep acc row = fst $ foldl' innerStep innerInit' row)
where innerInit' = ((adjust1 acc row), innerInit row)
innerInit row = ... -- same as innerInit above
innerStep (outAcc, inAcc) c = (outAcc', inAcc')
where inAcc' = adjust2 inAcc c
outAcc' = adjust3 outAcc c inAcc'
注意到具有不变性,我们不得不指出outAc'
取决于inAcc'
,而不是inAcc
,这意味着innerVar
之后的“状态” 它已更新。
现在你可能会说“哇,Haskell看起来很难看,为什么我会想要使用Haskell”。是的,它确实看起来很难看,但仅仅因为我将它定制为命令式代码的直接翻译。一旦你习惯使用 folds 而不是“遍历列表”,那么你会发现折叠是一种非常强大的技术,它可以让你以比循环更优雅的方式做很多事情。允许。
答案 3 :(得分:3)
就是这样:
[c | x <- xs, c <- x]