[英]How do I return a list of merged tuples?
Currently I have a list of tuples [ (1 , [1]) , (2 , [1]) , (3 , [1]) , (1 , [2]) , (3 , [2]) , (1 , [3]) ].目前我有一个元组列表 [ (1 , [1]) , (2 , [1]) , (3 , [1]) , (1 , [2]) , (3 , [2]) , (1 , [3]) ]。 I'd like to return a list of [ (1 , [1,2,3]) , (2 , [1]) , (3 , [1,2]) ].
我想返回 [ (1 , [1,2,3]) , (2 , [1]) , (3 , [1,2]) ] 的列表。
I have written a merge method that merges two tuples.我编写了一个合并两个元组的合并方法。
merge :: Ord a => (a,[Int]) -> (a,[Int]) -> (a,[Int])
merge (x,y) (w,z) = (x, y ++ z )
And a method that checks if the first element of each tuple is equal.以及检查每个元组的第一个元素是否相等的方法。
isEqual :: Ord a => (a,[Int]) -> (a,[Int]) -> Bool
isEqual (x,y) (w,z)
| x == w = True
| otherwise = False
I'm having trouble coming up with a way to run the isEqual and merge methods on each element though to get to the answer.我在想出一种在每个元素上运行 isEqual 和 merge 方法的方法时遇到了麻烦,但为了得到答案。 Would you guys recommend a fold or a recursive method?
你们会推荐折叠方法还是递归方法? Thanks!
谢谢!
Generally, to solve this type of problem efficiently , you need to store the values in a map structure that can be easily accessed by the "key" on which you're matching.通常,要有效地解决此类问题,您需要将值存储在地图结构中,该结构可以通过您匹配的“键”轻松访问。 That way, when you run across
(1, [2])
, you can quickly consult the map, see that you already have (1, [1])
, and combine them to get (1, [1,2])
.这样,当你遇到
(1, [2])
,你可以快速查阅地图,看到你已经有了(1, [1])
,并将它们组合起来得到(1, [1,2])
。 Later, when you run across (1, [3])
, you can quickly find (1, [1,2])
in the map and combine them to get (1, [1,2,3])
, and so on...之后,当你跑到
(1, [3])
,你可以在地图中快速找到(1, [1,2])
并将它们组合起来得到(1, [1,2,3])
,依此类推...
For this specific problem, there's a short solution using facilities in Data.Map
:对于这个特定问题,有一个使用
Data.Map
的工具的简短解决方案:
import qualified Data.Map.Strict as Map
gather :: (Ord a) => [(a, [Int])] -> [(a, [Int])]
gather = Map.toList . Map.fromListWith (++) . reverse
after which:之后:
> gather [(1 , [1]) , (2 , [1]) , (3 , [1]) , (1 , [2]) , (3 , [2]) , (1 , [3])]
[(1,[1,2,3]),(2,[1]),(3,[1,2])]
Here, Map.fromListWith
runs through a list of key-value pairs [(k,v)]
and adds them, one by one, to a new map.在这里,
Map.fromListWith
遍历键值对列表[(k,v)]
并将它们一个一个地添加到新映射中。 As each pair is added, if the key isn't already in the map, the value (in your case, a singleton value like [1]
or [2]
) is added under that key.添加每一对时,如果键不在地图中,则值(在您的情况下,像
[1]
或[2]
这样的单例值)将添加到该键下。 If the key is already in the map, the new value is combined with the old value using the supplied function (++)
(ie, as new_singleton_value ++ existing_list_of_values
).如果密钥是已经在图中,新的值与使用提供的功能的旧值组合
(++)
即,作为, new_singleton_value ++ existing_list_of_values
)。 This has the effect of creating a list of values in reverse order from the input list, so that's why I pre-processed the input list with reverse
.这具有从输入列表以相反顺序创建值列表的效果,因此这就是我使用
reverse
预处理输入列表的原因。 (If the order doesn't matter, you should drop it.) (如果顺序无关紧要,您应该放弃它。)
A more common variant of this problem is writing a function that takes a list of pairs:这个问题的一个更常见的变体是编写一个函数,它接受一个对列表:
[(1,1), (2,1), (3,1), (1,2), (3,2), (1,3)]
where the values aren't already lists.其中值尚未列出。 The solution is the same.
解决方法是一样的。 You just pre-process the list with
map (\\(k,v) -> (k,[v])
. This solution is covered in the other question mentioned in the comments.您只需使用
map (\\(k,v) -> (k,[v])
对列表进行预处理。评论中提到的另一个问题涵盖了此解决方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.