我正在尝试编写一个函数来选择具有较低值的元组,而元组由一个单词和一个值组成。
例如,对于像这样的元组列表:[(“CHURCH”,262),(“PENCIL”,311),(“FLOUR”,175),(“FOREST”,405),(“ CLASS“,105)],函数将返回(”CLASS“,105)
有人可以帮帮我吗? :)
非常感谢你!
答案 0 :(得分:7)
您正在寻找minimumBy
模块中的Data.List
函数。它的类型是
minimumBy :: (a -> a -> Ordering) -> [a] -> a
在您的情况下,从comparing
模块导入Data.Ord
也很有用,该模块的类型为
comparing :: Ord a => (b -> a) -> b -> b -> Ordering
这可以让你给它一个“访问者”功能来创建一个订单。所以在这种情况下你可以做到
minimumSnd :: [(String, Int)] -> (String, Int)
minimumSnd = minimumBy (comparing ???)
我会让你填写???
,此时应该很容易。您的访问者函数传递给comparing
的类型是什么?
如果您想为此编写自定义函数,我建议使用fold
模式。我们也可以借此机会通过返回Maybe
类型使其更安全,更一般的是不要求它成为(String, Int)
的列表:
minimumSnd :: (Ord b) => [(a, b)] -> Maybe (a, b)
minimumSnd = go Nothing
where
-- If the list is empty, just return our accumulator
go acc [] = acc
-- If we haven't found a minimum yet, grab the first element and use that
go Nothing (x:xs) = go (Just x) xs
-- If we have a minimum already, compare it to the next element
go (Just currentMin) (x:xs)
-- If it's <= our current min, use it
| snd x <= snd currentMin = go (Just x) xs
-- otherwise keep our current min and check the rest of the list
| otherwise = go (Just currentMin) xs
答案 1 :(得分:1)
试试这个:
foldl1 (\acc x -> if snd x < snd acc then x else acc) <your list>
通过将列表的当前元素与下一个元素进行比较来折叠列表。如果下一个元素的第二个值小于当前元素的值,则它是累加器的新值。否则累加器保持不变。重复此过程,直到遍历整个列表。
答案 2 :(得分:1)
我是Haskell的初学者,但无论如何我想找到一个有效的解决方案并提出:
minTup' :: [(String, Int)] -> Maybe (String, Int) -> (String, Int)
minTup' [] (Just x)= x
minTup' (x:xs) Nothing = minTup' xs (Just x)
minTup' ((s,n):xs) (Just (s',n'))
| n < n' = minTup' xs (Just (s,n))
| otherwise = minTup' xs (Just (s',n'))
minTup :: [(String, Int)] -> (String, Int)
minTup [] = error "Need a list of (String,Int)"
minTup x = minTup' x Nothing
main = do
print $ minTup [("CHURCH",262),("PENCIL",311),("FLOUR",175),("FOREST",405),("CLASS",105)]
print $ minTup [("CHURCH",262)]
print $ minTup []