我想在Haskell中做一个连接列表。 我有[1,2,3]和[4,5,6] 我想生产[14,15,16,24,25,26,34,35,36]。 我知道我可以使用zipWith或者sth,但是如何做到相当于: fore_在first_array中 foreach in second_array
我想我必须使用map和half curried函数,但实际上不能单独使用它:S
答案 0 :(得分:19)
您可以使用列表理解来执行此操作:
[x * 10 + y | x <- [1..3], y <- [4..6]]
实际上这是嵌套循环的直接转换,因为第一个是外/慢索引,第二个是更快/内索引。
答案 1 :(得分:12)
您可以利用列表是monad并使用 do notation 的事实:
do
a <- [1, 2, 3]
b <- [4, 5, 6]
return $ a * 10 + b
您还可以利用列表是应用仿函数的事实(假设您已导入Control.Applicative
):
(+) <$> (*10) <$> [1,2,3] <*> [4,5,6]
两者都会产生以下结果:
[14,15,16,24,25,26,34,35,36]
答案 2 :(得分:5)
如果您真的希望在代码中看到for
,您还可以执行以下操作:
for :: [a] -> (a -> b) -> [b]
for = flip map
nested :: [Integer]
nested = concat nested_list
where nested_list =
for [1, 2, 3] (\i ->
for [4, 5, 6] (\j ->
i * 10 + j
)
)
答案 3 :(得分:1)
嵌套循环对应于map
或类似函数的嵌套用法。第一个近似值:
notThereYet :: [[Integer]]
notThereYet = map (\x -> map (\y -> x*10 + y) [4, 5, 6]) [1, 2, 3]
这为您提供了嵌套列表,您可以通过两种方式消除这些列表。一种是使用concat :: [[a]] -> [a]
函数:
solution1 :: [Integer]
solution1 = concat (map (\x -> map (\y -> x*10 + y) [4, 5, 6]) [1, 2, 3])
另一个是使用这个内置函数:
concatMap :: (a -> [b]) -> [a] -> [b]
concatMap f xs = concat (map f xs)
使用:
solution2 :: [Integer]
solution2 = concatMap (\x -> map (\y -> x*10 + y) [4, 5, 6]) [1, 2, 3]
其他人提到了列表推导和列表monad,但那些真正自下而上是concatMap
的嵌套用法。
答案 4 :(得分:1)
因为已经说过do
符号和列表理解。我知道的唯一其他选项是通过liftM2
中的Control.Monad
组合器。这与前两个完全相同。
liftM2 (\a b -> a * 10 + b) [1..3] [4..6]
答案 5 :(得分:0)
两个整数列表串联的一般解决方案是:
concatInt [] xs = xs
concatInt xs [] = xs
concatInt xs ys = [join x y | x <- xs , y <- ys ]
where
join x y = firstPart + secondPart
where
firstPart = x * 10 ^ lengthSecondPart
lengthSecondPart = 1 + (truncate $ logBase 10 (fromIntegral y))
secondPart = y
示例:concatInt [1,2,3] [4,5,6] == [14,15,16,24,25,26,34,35,36]
更复杂的例子: concatInt [0,2,10,1,100,200] [24,2,999,44,3] == [24,2,999,44,3,224,22,2999,244,23,1024,102,10999,1044,103,124,12, 1999,144,13,10024,1002,100999,10044,1003,20024,2002,200999,20044,2003]