Kshitij Saraogi
Kshitij Saraogi

Reputation: 7619

How to define duplicate items in a Python tuple?

What are some good ways to define a tuple consisting of integers where the number of occurrences of each item is known ?

For example,

I want to define a tuple with 3 2's, 2 4's and 1, 3, 5 occur once.

For this, I can always go the manual way :

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

However, this becomes a bit messy when the number of items in the list is large. So, I want to know what are some ways to automate the task of generating the desired number of duplicates of each item.

Upvotes: 4

Views: 8470

Answers (7)

xirururu
xirururu

Reputation: 5508

If your tuple has not many number, you can do it in the simplest way.

(1,)+(2,)*3+(3,)+(4,)*2+(5,)

Otherwise, just turn it into a function.

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)

you can also call it with:

val = ((1,1),(2,3),(3,1),(4,2),(5,1))
myTuple(*val)
>>>(1, 2, 2, 2, 3, 4, 4, 5)

Upvotes: 2

gboffi
gboffi

Reputation: 25083

You can define the following function

def a_tuple(*data):
    l = []
    for i, cnt in data: l.extend([i]*cnt)
    return tuple(l)

and use it like this

print(a_tuple((1,1), (2,3), (3,1), (4,2), (5,1)))

to produce the following output

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

Have a look to the .extend() method of list if you don't understand how the function works.

Upvotes: 0

C Panda
C Panda

Reputation: 3415

So you want the inverse function of collections.Counter. Here is how you could do it,

# 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

Upvotes: 0

Jared Goguen
Jared Goguen

Reputation: 9010

If you have a tuple of tuples denoting the value and frequency, you can do the following:

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)

Or, if you know that the values are always going to be 1, 2, 3, ..., n, you can use enumerate with a tuple of the frequencies.

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)

If you're curious about the use of the double comprehension in the generator expression, you may want to check out this question.

Upvotes: 2

aychedee
aychedee

Reputation: 25609

Something like this could work:

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

Upvotes: 0

Peter DeGlopper
Peter DeGlopper

Reputation: 37344

One way is to use sequence multiplication. Here's a simple version that makes no attempt to avoid creating unnecessary intermediate objects:

accumulator = ()
for (val, count) in some_data_structure:
    accumulator += (val,) * count

That can be improved, the main point is to demonstrate that (1,) * 5 gives you (1, 1, 1, 1, 1). Note that this copies the object reference - that's fine for integers, but can cause confusion if you're trying to multiply a sequence of mutable objects.

Upvotes: 2

Dan D.
Dan D.

Reputation: 74655

You can do it like this:

>>> (1,) * 1 + (2,) * 3 + (4,) * 2 + (5,) * 1
(1, 2, 2, 2, 4, 4, 5)

Upvotes: 6

Related Questions