所以我得到了一个分数列表,并想从中创建一个排名列表。如果分数相同,则共享排名。
例如,如果我有一个像这样的分数列表
[100, 100, 50, 50, 20]
生成的列表将是
[(100, 1), (100, 1), (50, 2), (50, 2), (20, 3)]
我想这是一个相当简单的任务,但我还没有解决它。我尝试通过模式匹配或折叠来做到这一点,但没有成功。
我上次失败的方法如下所示:
scores = [100, 100, 50, 50, 20, 10]
ranks = foldr (\x acc -> if x == (fst $ last acc)
then last acc:acc
else (x, (+1) $ snd $ last acc):acc) [(head scores, 1)] scores
感谢任何帮助。
最佳答案
此解决方案与 Willem 的解决方案非常相似,只是它没有明确使用递归。许多风格指南,包括the Haskell wiki ,如果存在涉及高阶函数的简单实现,建议避免显式递归。在您的情况下,您的函数是 scanl
的非常简单的使用,它折叠一个具有累积值的列表(在您的情况下,累加器是当前排名和分数)并存储中间结果。
ranks :: Eq a => [a] -> [(a, Int)]
-- Handle the empty case trivially.
ranks [] = []
-- Scan left-to-right. The first element of the result should always
-- have rank 1, hence the `(x, 1)' for the starting conditions.
ranks (x:xs) = scanl go (x, 1) xs
-- The actual recursion is handled by `scanl'. `go' just
-- handles each specific iteration.
where go (curr, rank) y
-- If the "current" score equals the next element,
-- don't change the rank.
| curr == y = (curr, rank)
-- If they're not equal, increment the rank and
-- move on.
| otherwise = (y, rank + 1)
通过避免显式递归,可以说更容易一眼看出函数的作用。我可以查看这个,立即看到 scanl
,并且知道该函数将使用某种状态(排名)从左到右迭代列表并生成中间结果。
关于haskell - 如何根据 Haskell 中的分数列表创建排名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51572782/