我想做一個Haskell連接列表。我有[1,2,3]和[4,5,6] ,我想製作[14,15,16,24,25,26,34,35,36]。 我知道我可以使用zipWith或某事,而是怎麼做相當於:在second_array嵌套循環等效
我想我一定要使用地圖和半咖喱功能 的foreach在first_array 的foreach,但真的不能孤軍奮戰:小號
我想做一個Haskell連接列表。我有[1,2,3]和[4,5,6] ,我想製作[14,15,16,24,25,26,34,35,36]。 我知道我可以使用zipWith或某事,而是怎麼做相當於:在second_array嵌套循環等效
我想我一定要使用地圖和半咖喱功能 的foreach在first_array 的foreach,但真的不能孤軍奮戰:小號
你可以使用列表理解來做到這一點:
[x * 10 + y | x <- [1..3], y <- [4..6]]
事實上,這是一個嵌套循環的直接翻譯,因爲第一個是外於/慢指數,而第二個是更快/內部索引。
您可以利用以下事實:名單單子,並使用做記號:
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]
嵌套循環對應於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]
其他人都提到列表推導和列表單子,但那些真正的底層嵌套使用concatMap
。
整數兩個列表的級聯的一般解決方案是這樣的:
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]
因爲已經有10個符號和列表理解。我知道的唯一的其他選項是通過Control.Monad
的liftM2
組合器。這與前兩個完全相同。
liftM2 (\a b -> a * 10 + b) [1..3] [4..6]
...只有更短(除了所有的第一個)。 :) nicccce! –