我试图获取这个元组列表:
[(2,"a"), (1,"a"), (1,"b"), (1,"c"), (2,"dd")]
进入此字符串输出
a 1,2
b 1
c 1
dd 2
我假设我需要使用unzip和unlines函数。但我也看到了一些使用show函数的解决方案,它使整数字符串成为可能。有什么想法吗?
答案 0 :(得分:2)
如果您有此列表:
pairs = [ ("a", [1,2]), ("b", [1]), ("c", [1]), ("dd", [2]) ]
然后您可以通过以下方式获得所需的输出:
putStrLn $ unlines [ x ++ " " ++ unwords (map show ys) | (x, ys) <- pairs ]
但你必须弄清楚如何首先获得pairs
列表。
答案 1 :(得分:2)
将问题分解为几个步骤。你真正想要做的是聚合在第二个位置具有相同字符串的所有元组,因此你将拥有像
这样的函数aggregate :: [(Int, String)] -> [([Int], String)]
因此,对于输入列表,您将获得输出
[([1, 2], "a"), ([1], "b"), ([1], "c"), ([2], "dd")]
您的提示是
aggregate items = someFunc (map (\(num, str) -> ([num], str)) items)
看看foldr
。在您提出有关foldr
的后续问题之前,可能有数百个stackoverflow答案显示如何使用它,花一些时间来弄清楚它或它会立即关闭作为副本。
然后你需要一个函数将这个表单的单个元组转换为单个String
来输出:
prettyPrint :: ([Int], String) -> String
prettyPrint (nums, str) = str ++ " " ++ joinWithComma (map show nums)
您必须自己实施joinWithComma
。然后,您需要计算此数据并为汇总列表中的每个项目打印,mapM_
和putStrLn
将是首选,因此您的main
可能看起来像
main :: IO ()
main = do
let inputList = [(2,"a"), (1,"a"), (1,"b"), (1,"c"), (2,"dd")]
mapM_ (putStrLn . prettyPrint) (aggregate inputList)
答案 2 :(得分:0)
一步一步地工作。您可以从groupBy
函数开始:
groupBy (\x y-> (snd x)==(snd y)) [(2,"a"), (1,"a"), (1,"b"), (1,"c"), (2,"dd")]
给你
[[(2,"a"),(1,"a")],[(1,"b")],[(1,"c")],[(2,"dd")]]
下一步是“累计”内部列表,map
和foldL
(并且根据您的要求,sortBy
}应该会有所帮助。如果你有这个,那么构造输出是微不足道的(使用show
,正如你已经提到的那样。)