我有一个高阶函数,需要:
results ["Red", "Blue", "Green", "Blue", "Blue", "Red"]
返回:
[(1,"Green"),(2,"Red"),(3,"Blue")]
我需要使用结果函数并创建一个名为winner的新函数:
winner :: [Party ] -> Party
winner xs =
将输出最常出现的颜色并删除元组中的第一个元素,如果两个颜色具有相同的出现次数,则输出两种颜色,例如:
winner ["Red", "Blue", "Green", "Blue", "Blue", "Red"]
输出:
"blue"
到目前为止,我已经尝试过使用snd和tail但是我一直都会遇到错误。 先感谢您。
答案 0 :(得分:9)
如果你有results
功能,那么
maximumBy :: (a -> a -> Ordering) -> [a] -> a
就足够了
import Data.List -- for maximumBy
import Data.Ord -- for comparing
winner = snd . maximumBy (comparing fst) . results
看到
如果两种颜色具有相同的出现次数,则输出两种颜色
你需要一个不同的类型 - 当然还有不同的实现,但仍然很容易使用库函数:
import Data.List
import Data.Ord
import Data.Function
winners :: [Party] -> [Party]
winners = map snd . head . groupBy ((==) `on` fst) . sortBy (flip $ comparing fst) . results
由于results
已经产生了一个排序列表 - 我不想仅仅依赖于示例输出 - 它不需要再次排序,我们可以使用
winners = map snd . last . groupBy ((==) `on` fst) . results
生成所有最常出现的元素的列表。如果只需要一个最常用的元素,可以用
获得winner = snd . last . results
来自排序频率列表。
答案 1 :(得分:4)
import Data.List
import Data.Ord
winner xs = head . maximumBy (comparing length) . group . sort $ xs
main = print $ winner ["Red", "Blue", "Green", "Blue", "Blue", "Red"]
看起来是最直接的方式。
答案 2 :(得分:3)
如果您想避免排序,可以使用具有finMax
功能的MultiSet。
答案 3 :(得分:1)
在winners
函数中,您将获得String
的列表,然后您可以通过应用results
函数将其转换为'(Int,String)'元组的列表。然后,您希望获取这些元组中的最后一个(假设results
按出现次数的升序返回元素)并返回该元组的第二个元素。你已经提到你已经尝试了snd
函数,所以唯一的麻烦就是中间步骤,获取元组列表的最后一个元素,对吗?
返回最后一个元素的函数类型应该是什么?它需要一个(Int, String)
元组列表并返回一个元组,所以对类型的猜测可能是[(Int, String)] -> (Int, String)
,但函数并不需要知道它正在处理列表中的元组。它只需要返回列表的最后一个元素,因此更好的类型可能是[a] -> a
。使用此类型,转到Hoogle并在搜索框中键入它,您将获得所需的功能作为第二个结果。
这应该足以获得仅返回单个结果的获胜者功能。如果你希望能够返回多个结果,那么 - 正如Daniel Fischer在他的回答中所说 - 你需要另一个签名和稍微复杂的实现。我认为最简单的方法是通过过滤掉那些没有最大出现次数的元组来找到与最后一个元组具有相同出现次数的所有元组(再次假设出现的升序),然后转换结果通过在列表上映射snd
,将元组列表添加到这些元组的第二个元素列表中:
winners :: [String] -> [String]
winners xs = map snd maxOccursTuples
where maxOccursTuples = filter isMaxOccursTuple occurrences
isMaxOccursTuple tuple = fst tuple == maxOccurs
maxOccurs = fst (last occurrences)
occurrences = results xs