获取元组列表的第一个元素

Get the first elements of a list of tuples

我有这个元组列表

[(4,'a'), (1,'b'), (2,'c'), (2,'a'), (1,'d'), (4,'e')]

我想获取每个元组的第一个元素,然后复制它以生成以下内容:"aaaabccaadeeee"

我想出了这段代码,但它只给了我第一个元组的副本。

replicate  (fst ( head [(4,'a'), (1,'b')])) ( snd ( head [(4,'a'), (1,'b')]))
--output is: "aaaa"

我想用 map for 来获取每个元组的副本,但我没有成功。

既然你已经知道如何找到单个元素的正确答案,那么你只需要一点递归就可以了

func :: [(Int, a)] -> [a]
func [] = []
func ((n, elem):rest) = (replicate n elem) ++ (func rest)

映射值也应该有效。您只需要将生成的字符串连接成一个即可。

func :: [(Int, a)] -> [a]
func xs = concat $ map func2 xs where 
              func2 (n, elem) = replicate n elem

或者,如果您熟悉 currying

func :: [(Int, a)] -> [a]
func xs = concat $ map (uncurry replicate) xs

最后,如果您习惯使用函数组合,则定义变为:

func :: [(Int, a)] -> [a]
func = concat . map (uncurry replicate)

使用 concatmap 很常见,有一个函数可以做到这一点。这是 concatMap.

func :: [(Int, a)] -> [a]
func = concatMap (uncurry replicate)

您关于尝试使用 map 的说法是正确的。但首先让我们看看为什么您的代码不起作用

replicate  (fst ( head [(4,'a'), (1,'b')])) ( snd ( head [(4,'a'), (1,'b')]))

要复制的第一个参数是列表的头部,即 (4, 'a')。然后你在这个上调用 fst,因此第一个参数是 4。第二个参数发生同样的事情,你得到 'a'。结果你看。

在使用 map 之前,让我们尝试使用递归来完成此操作。您想要获取列表的一个元素并对其应用复制,然后将其与对第二个元素应用复制的结果组合。

generate [] = []    
generate (x:xs) = replicate (fst x) (snd x) ++ generate xs

请注意,我正在使用模式匹配来获取列表的第一个元素。您也可以使用模式匹配来获取元组中的元素,这样就不需要使用 fst/snd 函数了。另请注意,我正在使用模式匹配来定义空列表的基本情况。

generate [] = []
generate ((x,y):xs) = replicate x y ++ generate xs

现在来 map,所以 map 会将你的函数应用到列表的每个元素,这是第一次尝试

generate (x,y) = replicate x y
map generate  xs

上面的结果会和递归略有不同。想一想,map 将对每个元素应用生成并将结果存储在列表中。 generate 创建一个列表。因此,当您应用地图时,您正在创建一个列表列表。如果需要,您可以使用 concat 将其展平,这将得到与递归相同的结果。

最后,如果你可以使用递归,那么你也可以使用折叠。 Fold 只会将函数应用于列表的每个元素和 return 累积结果(广义上讲)。

--first parameter is the function to apply, second is the accumulator, third is your list
foldr step [] xs
   where step (x,y) acc = 
                   (replicate x y) ++ acc

在这里我再次在函数步骤中使用模式匹配来提取元组的元素。

ls = [(4,'a'), (1,'b'), (2,'c'), (2,'a'), (1,'d'), (4,'e')] 

concat [replicate i x | (i, x) <- ls]

会给

"aaaabccaadeeee"

免积分版

concat . map (uncurry replicate)