haskell - 使用元组列表

标签 haskell tuples

我一直在尝试解决这个问题,但就是想不通。所以,我有一个包含元组的列表,例如:

[("Mary", 10), ("John", 45), ("Bradley", 30), ("Mary", 15), ("John", 10)]

我想要得到的是一个包含元组的列表,如果名称相同,则应添加这些元组的编号,如果不相同,则该元组也必须是最终列表的一部分,例如:

[("Mary",25), ("John", 55), ("Bradley", 30)]

我不知道我是否解释得很好,但我想您可能会通过示例理解。

我已经试过了,但它不起作用:

test ((a,b):[]) = [(a,b)]
test ((a,b):(c,d):xs) | a == c = (a,b+d):test((a,b):xs)
                      | otherwise = (c,d):test((a,b):xs)

最佳答案

用列表做这类事情总是很尴尬,因为它们的顺序性质——它们并不真正适合“查找匹配项”或“通过组合列表元素的特定组合计算新列表”之类的操作或其他本质上不连续的事物。

如果您退后一步,您真正想要做的是,对于列表中的每个不同的 String,找到与其关联的所有数字并将它们相加。这听起来更适合键值样式的数据结构,在 Haskell 中最标准的是 is found in Data.Map ,它为您提供任何值类型和任何有序键类型(即 Ord 的实例)的键值映射。

因此,要从您的列表构建一个 Map,您可以使用 Data.Map 中的 fromList 函数... ,期望以键值元组列表的形式输入。所以你可以这样做......

import qualified Data.Map as M

nameMap = M.fromList [("Mary", 10), ("John", 45), ("Bradley", 30), ("Mary", 15), ("John", 10)]

...但这并不好,因为直接插入它们会覆盖数字而不是添加它们。你可以use M.fromListWith to specify how to combine values当插入重复的键时——在一般情况下,通常使用它来为每个键或类似的东西构建一个值列表。

但在您的情况下,我们可以直接跳到所需的结果:

nameMap = M.fromListWith (+) [("Mary", 10), ("John", 45), ("Bradley", 30), ("Mary", 15), ("John", 10)]

如果找到一个新名称,这将直接插入,否则它将在副本上添加值(数字)。如果愿意,您可以使用 M.toList 将其转回元组列表:

namesList = M.toList $ M.fromListWith (+) [("Mary", 10), ("John", 45), ("Bradley", 30), ("Mary", 15), ("John", 10)]

这给了我们 [("Bradley",30),("John",55),("Mary",25)] 的最终结果。

但是如果您想对姓名/号码集合做更多的事情,在完成之前将其保留为 Map 可能更有意义。

关于haskell - 使用元组列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14095496/

相关文章:

haskell - 将导管合二为一

haskell - 是否可以在 Haskell 中分析空间使用情况

c++ - 如何创建元组列表 C++

parsing - 在 Haskell 中解析谓词

haskell - 为什么 Data.Traversable 中的 'for' 接受单子(monad) Action ?

haskell - 在 Haskell 中定义逻辑运算符

c++ - 演绎指南和可变参数模板

java - 检查java中字典中是否存在元组键

python - Python 中的列表/元组切片语法中是否存在某种表达式求值?

Python比较2个列表和2个元组与等号