Haskell将列表转换为元组列表

10

我有一个像这样的列表:

["peter","1000","michell","2000","kelly","3000"]

我想将其转换为

[("peter",1000),("michell", 2000),("kelly",3000)]

请帮忙。 谢谢。

3个回答

17
cnv :: [String] -> [(String, Integer)]
cnv [] = []
cnv (k:v:t) = (k, read v) : cnv t

如果你想处理奇数长度,只需在最后一个之前添加cnv [x] =变体即可。


1
你能解释一下这行代码吗?cnv (k:v:t) = (k, read v) : cnv t?据我所知,k v t是列表中的参数,其中k是头部,v是尾部,cnv t是下一个元素作为k。我的理解正确吗?因为之前我有这样的函数。convert :: [String] -> [(String, Integer)] convert [] = [] convert (x:y:xs) = (x, y)convert xs为什么当我添加:xs时它就不起作用了?k v t代表单个元素还是整个列表? - nicholas
3
k:v:t 中,k 是头部,而 v:t 是尾部。因此,k:v:t 将列表的前两项放入 kv 中,并将剩余的尾部放入 t 中。你的代码有两个明显的问题:(a) (x,y) 的类型是 (String,String),而不是 (String,Integer);(b) 在 convert xs 之前没有冒号。你不能只写 :xs,因为你需要 [(String,Integer)],但是 xs 的类型是 [String]。另外,一个格式化提示:使用四个空格缩进行来获得代码块(或者选择代码并点击“101010”按钮),并用反引号 (`...code...`) 包围代码片段。 - Antal Spector-Zabusky
(x:xs)这意味着x是头部,xs是其余元素的尾部。感谢您的解释。 - nicholas
2
@Antal S-Z是正确的。(k:v:t)等同于(k:(v:t)),因为在GHC.Types中声明infixr 5:(也就是数据[] a = [] | a:[a]告诉你(v:t)[]的含义)。 - ony
任何例子。如何手动完成?我不明白你在这里说什么。(k:v:t) 相当于 (k:(v:t)),因为在 GHC.Types 中声明了 infixr 5 :(同时 data [] a = [] | a : [a] 也会告诉你 (v:t) 或 [] 的含义)。 - nicholas
infixr 5 :语句表示:从右侧开始结合,优先级为5。换句话说,w:x:y:zw:(x:(y:z)),而不是((w:x):y):z。数字5告诉你它在优先级链中的位置;例如,由于*+先出现,因此*的优先级为7,而+的优先级为6。data [] a = [] | a : [a]声明告诉你:[]的定义,即它们构造列表的部分等等。至于格式:只需在代码前面输入“`”,然后在代码后面输入“`”。阅读编辑帮助获取更多信息。 - Antal Spector-Zabusky

8

2
这绝对更自然。Split库并没有得到足够的关注。这很遗憾,因为它非常有用。 - Antal Spector-Zabusky
请注意,splitEvery 现在似乎已经被弃用了;请使用 chunksOf 代替。 - sevko

3

对于这样的任务,我发现拥有一个stride函数方便从列表中获取每个第n个元素:

stride _ [] = []
stride n (x:xs) = x : stride n (drop (n-1) xs)

它可以用来将列表转换为一对:
toPairs xs = zip (stride 2 xs) (stride 2 (drop 1 xs))

一个例子(请注意,如果最后一个元素没有配对,则可能被抛弃):
ghci> stride 2 [1..5]
[1,3,5]
ghci> toPairs [1..7]
[(1,2),(3,4),(5,6)]

它甚至可以轻松扩展到三元组或更长的元组:

toTriplets xs = zip3 as bs cs
  where as = stride 3 xs
        bs = stride 3 $ drop 1 xs
        cs = stride 3 $ drop 2 xs

要在您的示例中将字符串转换为整数,您可以将read函数映射到第二个步幅上:
let lst = ["peter","1000","michell","2000","kelly","3000"] in
zip (stride 2 lst) (map read . stride 2 . drop 1 $ lst) :: [(String,Int)]

这将会得到:

[("peter",1000),("michell",2000),("kelly",3000)]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接