定义一个由整数组成的元组(其中每个项的出现次数是已知的)的一些好方法是什么?
例如,
我想定义一个具有3 2、2 4和1、3、5的元组出现一次。
为此,我可以一直采用手动方式:
foo = (1, 2, 2, 2, 3, 4, 4, 5)
然而,当列表中的项目数量很大时,这会变得有点混乱。所以,我想知道哪些方法可以使生成每个项目所需数量的副本的任务自动化。
如何确定重复次数?
@他们是事先知道的。我已经在问题本身中说明了这一点。
您还暗示项目的数量可能会改变。
你可以这样做:
>>> (1,) * 1 + (2,) * 3 + (4,) * 2 + (5,) * 1
(1, 2, 2, 2, 4, 4, 5)
号
谢谢@dan d这对我很好+1
如果有一个表示值和频率的元组,可以执行以下操作:
tuples = ((1,1), (2,3), (3,1), (4,2), (5,1))
tuple(i for i, n in tuples for _ in range(n)) # Use xrange in Python 2.X
# (1, 2, 2, 2, 3, 4, 4, 5)
。
或者,如果你知道这些值总是1,2,3,…,n,你可以用enumerate和一组频率。
freqs = (1, 3, 1, 2, 1)
tuple(i for i, n in enumerate(freqs, 1) for _ in range(n))
# (1, 2, 2, 2, 3, 4, 4, 5)
如果您对生成器表达式中双重理解的用法感到好奇,那么您可能需要检查这个问题。
立即投反对票?介意提供理由吗?
我不是投反对票的人,但也许能解释一下发生了什么会有帮助?这基本上与我的答案中的想法相同,做了我提到的改进之一,以避免创建一些不必要的中间元组。
对于这样一个简单的任务来说,这太过分了。sum(..., [])的复杂度是二次的。
@很公平,它确实概括了这个问题。嵌套的生成器应该避免额外的复杂性。我将取消sum方法。
一种方法是使用序列乘法。下面是一个简单的版本,它不会试图避免创建不必要的中间对象:
accumulator = ()
for (val, count) in some_data_structure:
accumulator += (val,) * count
这是可以改进的,重点是证明(1,) * 5给了你(1, 1, 1, 1, 1)。请注意,这复制了对象引用——对于整数来说没问题,但是如果您试图将一系列可变对象相乘,可能会导致混淆。
如果你的元组没有多少个数字,你可以用最简单的方法来做。
(1,)+(2,)*3+(3,)+(4,)*2+(5,)
否则,只需将其转换为函数即可。
def myTuple(*val):
return sum(((i,) * n for i, n in val), ())
myTuple((1,1),(2,3),(3,1),(4,2),(5,1))
>>>(1, 2, 2, 2, 3, 4, 4, 5)
。
您也可以通过以下方式调用它:
val = ((1,1),(2,3),(3,1),(4,2),(5,1))
myTuple(*val)
>>>(1, 2, 2, 2, 3, 4, 4, 5)
号
您可以定义以下函数
def a_tuple(*data):
l = []
for i, cnt in data: l.extend([i]*cnt)
return tuple(l)
。
像这样使用
print(a_tuple((1,1), (2,3), (3,1), (4,2), (5,1)))
产生以下输出
(1, 2, 2, 2, 3, 4, 4, 5)
。
如果您不了解函数的工作原理,请查看清单的.extend()方法。
所以你需要EDOCX1的反函数。你可以这样做,
# make a dict of counts (list of tuples is better)
counts = {1: 1, 2: 3, 4: 2, 3:1, 5: 1}
t = tuple(k for k,v in sorted(counts.items()) for _ in range(v))
(1, 2, 2, 2, 3, 4, 4, 5)
# for k,v in list_of_tuples, for a list of tuples
。
类似这样的事情可能会奏效:
>>> result = tuple()
>>> for item, repeat in ((1, 1), (2, 3), (3, 1), (4, 2), (5, 1)):
... result = result + (item,) * repeat
>>> result
(1, 2, 2, 2, 3, 4, 4, 5)