Reputation: 7619
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
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
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
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
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
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
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
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