haskell - 如何根据 Haskell 中的分数列表创建排名?

标签 haskell

所以我得到了一个分数列表,并想从中创建一个排名列表。如果分数相同,则共享排名。

例如,如果我有一个像这样的分数列表

[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/

相关文章:

python - Haskell、python 和 c 中的函数之间的主要区别是什么?

string - Haskell中String和Data.Text之间的自动转换

haskell - 了解 Haskell 类型签名

haskell - 关于通过多个嵌套功能级别进行映射

Haskell:对单个值运行 IO 操作列表

haskell - 在 Haskell 中将 [IO Int] 转换为 IO [Int]?

haskell - 将表示二进制数的字符串转换为以 10 为基数的字符串 haskell

haskell - 是否有一个单子(monad)的术语也是一个共单子(monad)?

haskell N00b : IntelliJ giving two errors

haskell - 如何在reactive-banana中使行为包含其他行为