获取元组列表的第一个元素
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)
使用 concat
和 map
很常见,有一个函数可以做到这一点。这是 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)
我有这个元组列表
[(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)
使用 concat
和 map
很常见,有一个函数可以做到这一点。这是 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)