多次打印出元组列表的每个元素

时间:2019-10-27 15:52:12

标签: haskell

给出一个像这样的元组列表[('a',2), ('b', 6), ('c', 1)],我每次都尝试在字符串中打印出char。

我正在一行中的字符串中寻找类似"aabbbbbbc"的输出。

我正在尝试使用replicate,例如replicate (snd x) (fst x)来做到这一点,但这没用。

4 个答案:

答案 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]组合mapconcat

Prelude> concatMap (\x -> replicate (snd x) (fst x)) [('a',2), ('b', 6), ('c', 1)]
"aabbbbbbc"

我们可以在此处使用模式匹配,以避免使用fstsnd

concatMap (\(x, y) -> replicate y x)

或者我们可以使用uncurry :: (a -> b -> c) -> (a, b) -> cflip :: (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"