输出一个元素我想要的次数 [英] Output an element the number of times I want

查看:64
本文介绍了输出一个元素我想要的次数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有此代码:

lado ::  [([Char],Int)] -> [[Char]]
lado xs = [a | (a,b) <- xs]

我需要输出:

> lado [("A",3),("B",2),("C",1)]
["A","B","C","A","B","A"]

我必须输出"A" 3次,然后是"B" 2倍于"C". 1次,但我只能通过此代码获得此["A","B","C"].

I have to output "A" 3 times, then "B" 2 times then "C" 1 time but I only get this ["A","B","C"] with this code.

推荐答案

您已经在尝试使用列表推导.多使用它们.

You already use list comprehensions in your attempt. Use them some more.

lado ::  [([Char],Int)] -> [[Char]]
lado xs = [a | (a,b) <- xs, b <- [1..b]]

测试:

> lado [("A",3),("B",2),("C",1)]
["A","A","A","B","B","C"]

正如你的问题所说,

我必须输出"A" 3次,然后是"B" 2倍,然后"C"为0. 1次

I have to output "A" 3 times, then "B" 2 times then "C" 1 time

但是如果您确实想要["A","B","C","A","B","A"],那么

But if it is really ["A","B","C","A","B","A"] you want, then

lado ::  [(a,Int)] -> [a]
lado []        = []
lado ((a,1):b) = a : lado b
lado ((a,n):b) = a : lado (b ++ [(a,n-1))])

,可以用Data.List中的unfoldr :: (b -> Maybe (a, b)) -> b -> [a]进行编码,

which can be coded with unfoldr :: (b -> Maybe (a, b)) -> b -> [a] from Data.List,

lado ::  [(a,Int)] -> [a]
lado xs = unfoldr g $ xs
  where
  g []        = Nothing
  g ((a,1):b) = Just (a, b)
  g ((a,n):b) = Just (a, b ++ [(a,n-1)])

可以用Prelude的iterate :: (a -> a) -> a -> [a]等模仿,例如

which can be emulated with Prelude's iterate :: (a -> a) -> a -> [a] etc., as

lado ::  [(a,Int)] -> [a]
lado xs = map (fst . head) . takeWhile ( ... ) . iterate g $ xs
  where
  g []            = []
  g ((a, ... ):b) = b
  g ((a,  n  ):b) = b ++ [(a, ... )]

测试:

> lado [("A",3),("B",2),("C",1)]
["A","B","C","A","B","A"]

填写空白...以使其起作用.

Fill in the blanks ... to make it work.

@dfeuer 所述,列表末尾重复出现的单例会损害整体效率.非常感谢他的投入和讨论,包括此处的两个答案和评论,甚至还有github 要点,这可以通过通常的FP范式(更不用说把戏")来反向建立列表来弥补,例如

as @dfeuer notes, the repeated singleton-appending at list's end is detrimental to overall efficiency. With big thanks to his input and discussion, including the two answers and comments here and even a github gist, this can be remedied by the usual FP paradigm (not to say "trick") of building a list in reverse, as

lado ::  [(a,Int)] -> [a]
lado xs = go (filter ((> 0) . snd) xs) []
  where
  go []       []  =  []
  go []        r  =  go (reverse r) []
  go ((a,1):b) r  =  a : go b r
  go ((a,n):b) r  =  a : go b ((a,n-1):r)

在所有输出中使用reverse成本摊销,这只会为每个输出项增加恒定的开销.

With the reverse cost amortized over all the output this will add only a constant overhead per each output item.

这篇关于输出一个元素我想要的次数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆