如何在Python元组中定义重复项?

4

有哪些好的方法可以定义一个由整数组成的元组,其中每个项目出现的次数已知?

例如,

我想定义一个元组,包含3个2、2个4和1个3、5,每个数字仅出现一次。

为此,我可以手动进行定义:

foo = (1, 2, 2, 2, 3, 4, 4, 5)

然而,当列表中的项目数量较大时,情况会变得有些混乱。因此,我想知道有哪些方法可以自动化生成每个项目所需数量的副本。


重复次数将如何确定? - vaultah
@vaultah 他们是事先已知的。我在问题本身中已经说明了这一点。 - Kshitij Saraogi
您还暗示了项目数量可能会发生变化。 - vaultah
7个回答

6
你可以这样做:
>>> (1,) * 1 + (2,) * 3 + (4,) * 2 + (5,) * 1
(1, 2, 2, 2, 4, 4, 5)

2
一种方法是使用序列乘法。以下是一个简单版本,它不尝试避免创建不必要的中间对象:
accumulator = ()
for (val, count) in some_data_structure:
    accumulator += (val,) * count

这可以得到改进,主要点是要展示 (1,) * 5 给你的结果是 (1, 1, 1, 1, 1)。请注意,这会复制对象引用 - 对于整数来说没问题,但如果您试图乘以一系列可变对象,则可能会引起混淆。


2
如果您有一个由元组表示值和频率的元组,可以执行以下操作:
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,则可以使用具有频率元组的枚举

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)

如果您对生成器表达式中双重理解的使用感到好奇,您可能想查看这个问题


我不是那个给你点踩的人,但或许解释一下会有所帮助?这基本上和我的答案是相同的思路,实现了我提到的其中一个改进,避免了创建一些不必要的中间元组。 - Peter DeGlopper
这对于如此简单的任务来说有些过度了。 sum(...,[]) 的复杂度是二次的。 - vaultah
@vaultah 好的,虽然这样做可以概括问题。但是嵌套生成器应该避免额外的复杂性。我会删除sum方法。 - Jared Goguen

2
如果你的元组中数量不多,可以用最简单的方法来处理。
(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)

0

可以尝试类似这样的代码:

>>> 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)

0

所以你想要 collections.Counter 的反函数。这是你可以做到的方法,

# 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

0
您可以定义以下函数。
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()列表方法


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接