给出一个像这样的元组列表[('a',2), ('b', 6), ('c', 1)]
,我每次都尝试在字符串中打印出char。
我正在一行中的字符串中寻找类似"aabbbbbbc"
的输出。
我正在尝试使用replicate
,例如replicate (snd x) (fst x)
来做到这一点,但这没用。
答案 0 :(得分:6)
如果有项目列表,则可以使用map :: (a -> b) -> [a] -> [b]
来构造一个列表,其中将给定功能应用于给定列表的所有元素。因此,我们可以在此处使用replicate
,例如:
map (\x -> replicate (snd x) (fst x))
以获得项目列表,其中对于项目('a', 2)
,我们得到"aa"
。对于样本数据,我们因此获得:
Prelude> map (\x -> replicate (snd x) (fst x)) [('a',2), ('b', 6), ('c', 1)]
["aa","bbbbbb","c"]
这当然是元素列表的列表。我们可以使用concat :: Foldable f => f [a] -> [a]
将元素串联在一起,也可以使用concatMap :: Foldable f => (a -> [b]) -> f a -> [b]
组合map
和concat
:
Prelude> concatMap (\x -> replicate (snd x) (fst x)) [('a',2), ('b', 6), ('c', 1)]
"aabbbbbbc"
我们可以在此处使用模式匹配,以避免使用fst
和snd
:
concatMap (\(x, y) -> replicate y x)
或者我们可以使用uncurry :: (a -> b -> c) -> (a, b) -> c
和flip :: (a -> b -> c) -> b -> a -> c
并将函数编写为:
concatMap (uncurry (flip replicate))
答案 1 :(得分:6)
这可以使用list comprehensions(其中xs
是您的元组列表)完成:
concat [replicate n x | (x, n) <- xs]
答案 2 :(得分:1)
让我们先定义一下
foo [('a',2), ('b', 6), ('c', 1)] = "aabbbbbbc"
这是正确的定义吗?是的。
它有问题吗?是的,这还不够普遍。它只会接受非常非常具体且狭窄的输入形式,并且会在其他所有内容上出错:
> foo [('a',2), ('b', 6), ('c', 1)]
"aabbbbbbc"
it :: [Char]
> foo [('a',2), ('b', 6), ('c', 2)]
"*** Exception: <interactive>:13:5-51: Non-exhaustive patterns in function foo
该定义还有其他问题吗?好吧,本质上并没有错,但是它缺少 type签名。 GHCi可以为我们推断类型:
> :t foo
foo :: (Num t, Eq t) => [(Char, t)] -> [Char]
但是看起来太笼统了。我们可以专门是
foo :: [(Char, Int)] -> [Char]
那么,使用这种类型,该定义可以做什么?从丢失的情况开始,我们添加
foo [('a',2), ('b', 6), ('c', 2)] = "aabbbbbbcc"
foo [('a',2), ('b', 6), ('c', 3)] = "aabbbbbbccc"
所有正确的情况。但是如何使它们更通用?
为此,我们尝试重新编写它并尝试查看其中的某些模式:
foo [('a',2), ('b', 6), ('c', 4)] = "aabbbbbbcccc"
= "aabbbbbb" ++ "cccc"
= "aabbbbbb" ++ replicate _ 'c'
该_
插槽中的值是多少?
回答后,您还可以完成此操作:
foo [('a',2), ('b', 6), ('c', n)] = "aabbbbbbcccc"
= "aabbbbbb" ++ "cccc"
= "aabbbbbb" ++ replicate _ 'c'
和这个:
foo [('a',2), ('b', m), ('c', n)] = "aabbbbbbcccc"
= "aabbbbbb" ++ "cccc"
= "aa" ++ replicate _ _ ++ replicate _ 'c'
和
不同吗?foo ( ('a',2) : [('b', m), ('c', n)] ) =
= replicate _ 'a' ++ foo [('b', m), ('c', n)]
?
对吗?您能继续这种思路吗?
答案 3 :(得分:1)
这基本上是一项折叠工作。
Prelude> foldr (\(c,n) r -> replicate n c ++ r) "" [('a',2), ('b', 6), ('c', 1)]
"aabbbbbbc"
我使用foldr
到累加器r
的头进行级联,效率更高。
或者对于单子方法,您可能会这样写
Prelude> let decode = (uncurry (flip replicate) =<<)
Prelude> decode [('a',2), ('b', 6), ('c', 1)]
Prelude> "aabbbbbbc"