I have a tuple:
a = (1,2,3)
and I need to add a tuple at the end
b = (4,5)
The result should be:
(1,2,3,(4,5))
Even if I wrap b in extra parents:
a + (b), I get (1,2,3,4,5) which is not what I wanted.
When you do a + b you are simply concatenating both the tuples. Here, you want the entire tuple to be a part of another tuple. So, we wrap that inside another tuple.
a, b = (1, 2, 3), (4,5)
print a + (b,) # (1, 2, 3, (4, 5))
>>> a = (1,2,3)
>>> b = (4,5)
>>> a + (b,)
(1, 2, 3, (4, 5))
tuple objects are immutable. The result you're getting is a result of the fact that the + (and +=) operator is overridden to allow "extending" tuples the same way as lists. So when you add two tuples, Python assumes that you want to concatenate their contents.
To add an entire tuple onto the end of another tuple, wrap the tuple to be added inside another tuple.
c = a + (b,) # Add a 1-tuple containing the tuple to be added.
print(c) # >>> (1, 2, 3, (4, 5))
Related
Consider this example:
>>> t = (1, 2, 3)
>>> a, b, c = t
>>> a, b, c
(1, 2, 3)
>>> a, *b = t
>>> a, b
(1, [2, 3])
Why do I get a list instead of a tuple when unpacking a tuple with a, *b = t ?
As described in PEP 3132, this is extended iterable unpacking. The type doesn't "change"; it is just defined that * unpacking will yield a list in all cases.
It was proposed for it to yield:
A tuple instead of a list:
Make the starred target a tuple instead of a list. This would be consistent with a function's *args, but make further processing of the result harder.
The same type as the right-hand side:
Try to give the starred target the same type as the source iterable, for example, b in a, *b = 'hello' would be assigned the string 'ello'. This may seem nice, but is impossible to get right consistently with all iterables.
Ultimately, these proposals were rejected.
For some more insight, see here and here.
You can find more information in this link https://www.python.org/dev/peps/pep-3132/ but I think it's essentially because this is generic iterable unpacking so it converts things to a list first to handle for the generic case:
Also, if the right-hand value is not a list, but an iterable, it has
to be converted to a list before being able to do slicing
I think tuple is a special case where the implementation could allow for it returned as a tuple, since tuples already allow slicing but it looks like the decision was made to implement the most generic version in this case.
In Python 3.0, the * operator was added to the multiple assignment syntax, allowing us to capture remaining items after an unpacking into a list. The * operator allows us to replace hard-coded slices near the ends of sequences.
Arccording your code:
>>> t = (1, 2, 3)
>>> a, b, c = t
>>> a, b, c
(1, 2, 3)
>>> a, *b = t
>>> a, b
(1, [2, 3])
The same code:
>>> t = (1, 2, 3)
>>> a, b, c = t
>>> a, b, c
(1, 2, 3)
>>> a, *b = t[0], t[1:]
>>> a, b
(1, [2, 3])
Read more here.
I am trying to sort numerical tuples by two arguments:
first argument, lenght of the tuple: the smaller the tuple, the better;
second argument, the n-th value of the tuple: if two tuples have the same lenght, then they should be ordered by the first numerical value by which they differ
For example, let's say we have these four tuples:
a = (2, 5) # len(a) == 2
b = (2, 5, 3) # len(b) == 3
c = (2, 4, 3) # len(c) == 3
d = (1, 4, 4, 8) # len(d) == 4
The result I'm willing to obtain is a function that will help me sort these tuples so that:
a is the first tuple (the smallest one)
b and c follows (the middle ones)
d is the last tuple (the longest one)
since b and c both get the same lenght, they shall be ordered so that c comes before b, because while their first value is the same, c's second values is smaller than b's
Therefore, the four tuples above should be listed as [a, c, b, d].
Question is: how do I do it, knowing that the tuples have no fixed length, and they might differ at any value from the first to the last one?
You can sort tuples with... tuples:
res = sorted([a, b, c, d], key=lambda x: (len(x), x))
# [(2, 5), (2, 4, 3), (2, 5, 3), (1, 4, 4, 8)]
The key is the key argument, which utilises an anonymous (lambda) function. Python sorts tuples by element. So the first element len(x) gives priority to length of tuple. The second element x gives secondary importance to sorting by the tuple itself, which itself is performed element-wise.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
E.g., why can't I do:
(0,1) + (2,2)
and get:
(2,3)
as a result?
Because the + operator is used to make a new tuple that is the combination of two other tuples. That is just how Python was designed.
To do what you want, you can use zip and a generator expression:
>>> t1 = (0,1)
>>> t2 = (2,2)
>>> tuple(x + y for x, y in zip(t1, t2))
(2, 3)
>>>
'+' operator concatenate tuples . if you want to sum tuples item you can use:
tuple(sum(x) for x in zip((0,1),(2,2)))
or
tuple(map(sum,zip((0,1),(2,2))))
Its because of you add tow tuple and + operation for tuples concatenate them ! you can use map and zip functions for that :
>>> map(sum,zip((0,1),(2,2)))
[2, 3]
or use a generator :
>>> tuple(i+j for i,j in zip((0,1),(2,2)))
(2, 3)
and a better way with operator.add:
>>> from operator import add
>>> map(add,(0,1),(2,2))
[2, 3]
Since Python thinks of tuples as lists that are immutable, adding two tuples is just like adding two lists. So, just as adding two lists will concatenate them:
>>> [1, 2] + [3, 4]
[1, 2, 3, 4]
adding two tuples will also concatenate them:
>>> (1, 2) + (3, 4)
(1, 2, 3, 4)
You can create a new tuple that consists of the sum of each pair with a few of Python's built-in functions:
>>> tuple(map(sum, zip((0, 1), (2, 2))))
(2, 3)
This works by using zip() on the two tuples to make a list of pairs:
>>> zip((0, 1), (2, 2))
[(0, 2), (1, 2)]
And using map() to apply sum() on each element of that list, to get a list of sums:
>>> map(sum, zip((0, 1), (2, 2)))
[2, 3]
And, finally, using tuple() to turn that from a list into a tuple.
Element-wise addition is a more specialized operation than concatenation. Fewer tuples could be added together: what would ('a','b') + (1,2,) equal?
Or ('a', 'b') + (1,2,3) for that matter?
Since concatenation is arguably the more commonly desired operation, and importantly, well defined for all tuples, it makes sense that addition of tuples performs concatenation.
I have an array of n numbers, say [1,4,6,2,3]. The sorted array is [1,2,3,4,6], and the indexes of these numbers in the old array are 0, 3, 4, 1, and 2. What is the best way, given an array of n numbers, to find this array of indexes?
My idea is to run order statistics for each element. However, since I have to rewrite this function many times (in contest), I'm wondering if there's a short way to do this.
>>> a = [1,4,6,2,3]
>>> [b[0] for b in sorted(enumerate(a),key=lambda i:i[1])]
[0, 3, 4, 1, 2]
Explanation:
enumerate(a) returns an enumeration over tuples consisting of the indexes and values in the original list: [(0, 1), (1, 4), (2, 6), (3, 2), (4, 3)]
Then sorted with a key of lambda i:i[1] sorts based on the original values (item 1 of each tuple).
Finally, the list comprehension [b[0] for b in ...] returns the original indexes (item 0 of each tuple).
Using numpy arrays instead of lists may be beneficial if you are doing a lot of statistics on the data. If you choose to do so, this would work:
import numpy as np
a = np.array( [1,4,6,2,3] )
b = np.argsort( a )
argsort() can operate on lists as well, but I believe that in this case it simply copies the data into an array first.
Here is another way:
>>> sorted(xrange(len(a)), key=lambda ix: a[ix])
[0, 3, 4, 1, 2]
This approach sorts not the original list, but its indices (created with xrange), using the original list as the sort keys.
This should do the trick:
from operator import itemgetter
indices = zip(*sorted(enumerate(my_list), key=itemgetter(1)))[0]
The long way instead of using list comprehension for beginner like me
a = [1,4,6,2,3]
b = enumerate(a)
c = sorted(b, key = lambda i:i[1])
d = []
for e in c:
d.append(e[0])
print(d)
Is there a way to get one value from a tuple in Python using expressions?
def tup():
return (3, "hello")
i = 5 + tup() # I want to add just the three
I know I can do this:
(j, _) = tup()
i = 5 + j
But that would add a few dozen lines to my function, doubling its length.
You can write
i = 5 + tup()[0]
Tuples can be indexed just like lists.
The main difference between tuples and lists is that tuples are immutable - you can't set the elements of a tuple to different values, or add or remove elements like you can from a list. But other than that, in most situations, they work pretty much the same.
For anyone in the future looking for an answer, I would like to give a much clearer answer to the question.
# for making a tuple
my_tuple = (89, 32)
my_tuple_with_more_values = (1, 2, 3, 4, 5, 6)
# to concatenate tuples
another_tuple = my_tuple + my_tuple_with_more_values
print(another_tuple)
# (89, 32, 1, 2, 3, 4, 5, 6)
# getting a value from a tuple is similar to a list
first_val = my_tuple[0]
second_val = my_tuple[1]
# if you have a function called my_tuple_fun that returns a tuple,
# you might want to do this
my_tuple_fun()[0]
my_tuple_fun()[1]
# or this
v1, v2 = my_tuple_fun()
Hope this clears things up further for those that need it.
General
Single elements of a tuple a can be accessed -in an indexed array-like fashion-
via a[0], a[1], ... depending on the number of elements in the tuple.
Example
If your tuple is a=(3,"a")
a[0] yields 3,
a[1] yields "a"
Concrete answer to question
def tup():
return (3, "hello")
tup() returns a 2-tuple.
In order to "solve"
i = 5 + tup() # I want to add just the three
you select the 3 by:
tup()[0] # first element
so all together:
i = 5 + tup()[0]
Alternatives
Go with namedtuple that allows you to access tuple elements by name (and by index). Details are at https://docs.python.org/3/library/collections.html#collections.namedtuple
>>> import collections
>>> MyTuple=collections.namedtuple("MyTuple", "mynumber, mystring")
>>> m = MyTuple(3, "hello")
>>> m[0]
3
>>> m.mynumber
3
>>> m[1]
'hello'
>>> m.mystring
'hello'