【发布时间】:2011-11-25 18:01:02
【问题描述】:
我需要找到矩阵中的最小元素。 我有一个解决方案,但并不完美。
type Matrix = [[Int]]
matMin :: Matrix -> Int
matMin [] = 99999999999
matMin (xs:xss) = minimum xs `min` matMin xss
谁能给我一个更好的解决方案的提示?
【问题讨论】:
我需要找到矩阵中的最小元素。 我有一个解决方案,但并不完美。
type Matrix = [[Int]]
matMin :: Matrix -> Int
matMin [] = 99999999999
matMin (xs:xss) = minimum xs `min` matMin xss
谁能给我一个更好的解决方案的提示?
【问题讨论】:
我能想到的最简单的就是matMin = minimum . concat
【讨论】:
看看map 函数。矩阵的最小值是每一行的最小值中的最小值:
Prelude> :t minimum . map minimum
minimum . map minimum :: Ord c => [[c]] -> c
【讨论】:
您的代码稍作调整,避免使用硬编码值:
type Matrix = [[Int]]
matMin :: Matrix -> Int
matMin [] = error "min is undefined for 0x0 matrix"
matMin [xs] = minimum xs
matMin (xs:xss) = minimum xs `min` matMin xss
或者坚持你的方法,你可以改用maxBound(因为Int是Bounded)。
matMin :: Matrix -> Int
matMin [] = maxBound
matMin (xs:xss) = minimum xs `min` matMin xss
事实上,这看起来像一个折叠。
matMin = foldl' (acc x -> minimum x `min` acc) maxBound
或者如果你想变得有点无意义
matMin = foldl' (flip (min . minimum)) maxBound
-- or if you don't like the flip
matMin = foldr (min . minimum) maxBound
请注意,此模式适用于任何矩阵“折叠”。
matFoldr :: (b -> c -> c) -- how to merge the accumulator with the result of mergeCells
-> ([a] -> b) -- how to merge a row of cells
-> c -- a starting accumulator value
-> [[a]] -- the matrix to fold over
-> c
matFoldr mergeRows mergeCells start = foldr (mergeRows . mergeCells) start
matMin = matFoldr min minimum maxBound
matMax = matFoldr max maximum minBound
matSum = matFoldr (+) sum 0
matProduct = matFoldr (*) product 1
如果我们真的想要,我们甚至可以做到,这样您就不必指定要使用哪个列表操作。
matEasyFold mergeRows start = matFoldr mergeRows mergeCells start
where mergeCells = foldr mergeRows start
matMin = matEasyFold min maxBound
matSum = matEasyFold (+) 0
-- etc
【讨论】:
非常感谢:-p 我解决得容易多了,但它与 Mihai 的答案非常相似
matMin :: Matrix -> Int
matMin xss = minimum(map minimum xss)
感谢您的帮助。
【讨论】: