有没有更好的方法来编写这个函数(即通过折叠在一行中)?
-- list -> rowWidth -> list of lists
listToMatrix :: [a] -> Int -> [[a]]
listToMatrix [] _ = []
listToMatrix xs b = [(take b xs)] ++ (listToMatrix (drop b xs) b)
答案 0 :(得分:4)
实际上这是一个很好的展开案例。 Data.List
方法unfoldr
与折叠列表不同,通过向其应用函数直到此函数返回Nothing
,从种子值创建列表。在我们到达将返回Nothing
的终止条件之前,函数返回Just (a,b)
,其中a
是列表的当前生成项,b
是种子的下一个值。在这种特殊情况下,我们的种子值是给定的列表。
import Data.List
chunk :: Int -> [a] -> [[a]]
chunk n = unfoldr (\xs -> if null xs then Nothing else Just (splitAt n xs))
*Main> chunk 3 [1,2,3,4,5,6,7,8,9]
[[1,2,3],[4,5,6],[7,8,9]]
*Main> chunk 3 [1,2,3,4,5,6,7,8,9,10]
[[1,2,3],[4,5,6],[7,8,9],[10]]
答案 1 :(得分:3)
是的,有更好的方法来编写此功能。但我并不认为让它成为一条线会改善任何事情。
(:)
代替列表连接(++)
进行单元素前置表达式[(take b xs)] ++ (listToMatrix (drop b xs) b)
效率低下。我并不意味着在性能方面效率低下,因为编译器可能会优化它,但是,在这里,你构建一个列表,然后在其上调用一个函数((++)
),它将解构它通过模式匹配。您可以使用(:)
数据构造函数直接构建列表,这允许您将单个元素添加到列表中。表达式变为take b xs : listToMatrix (drop b xs) b
splitAt
以避免两次运行列表import Data.List (splitAt)
listToMatrix :: [a] -> Int -> [[a]]
listToMatrix xs b = row : listToMatrix remaining b
where (row, remaining) = splitAt b xs
Maybe
listToMatrix :: [a] -> Int -> Maybe [[a]]
listToMatrix xs b
| length xs `mod` b /= 0 = Nothing
| null xs = Just []
| otherwise = Just $ row : listToMatrix remaining b
where (row, remaining) = splitAt b xs
通过定义辅助函数,您甚至可以避免每次检查是否有正确数量的元素:
listToMatrix :: [a] -> Int -> Maybe [[a]]
listToMatrix xs b
| length xs `mod` b /= 0 = Nothing
| otherwise = Just (go xs)
where go [] = []
go xs = row : go remaining
where (row, remaining) = splitAt b xs
矩阵在每行中具有相同数量的元素,而嵌套列表不允许确保这种条件。要确保每行具有相同数量的元素,您可以使用matrix
或hmatrix
答案 2 :(得分:2)
不,虽然我希望chunksOf
在标准库中。如果您愿意,可以从这里获取:https://hackage.haskell.org/package/split-0.2.3.2/docs/Data-List-Split.html
注意更好的定义是:
listToMatrix xs b = (take b xs) : (listToMatrix (drop b xs) b)
虽然这可能会编译到同一个核心。您也可以使用splitAt
,但这可能会执行相同的操作。
listToMatrix xs b = let (xs,xss) = splitAt b xs in xs : listToMatrix xss
答案 3 :(得分:0)
你可以使用它,想法是采取主列表的所有块,这是一种不同的方法,但基本上做同样的事情:
Prelude> let list2Matrix n xs = map (\(x ,y)-> (take n) $ (drop (n*x)) y) $ zip [0..] $ replicate (div (length xs) n) xs
Prelude> list2Matrix 10 [1..100]
[[1,2,3,4,5,6,7,8,9,10],[11,12,13,14,15,16,17,18,19,20],[21,22,23,24,25,26,27,28,29,30],[31,32,33,34,35,36,37,38,39,40],[41,42,43,44,45,46,47,48,49,50],[51,52,53,54,55,56,57,58,59,60],[61,62,63,64,65,66,67,68,69,70],[71,72,73,74,75,76,77,78,79,80],[81,82,83,84,85,86,87,88,89,90],[91,92,93,94,95,96,97,98,99,100]]