I have a list like below where the first element is the id and the other is a string:
[(1, u'abc'), (2, u'def')]
I want to create a list of ids only from this list of tuples as below:
[1,2]
I’ll use this list in __in so it needs to be a list of integer values.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
>>> a = [(1, u'abc'), (2, u'def')] >>> [i[0] for i in a] [1, 2]
Method 2
Use the zip function to decouple elements:
>>> inpt = [(1, u'abc'), (2, u'def')] >>> unzipped = zip(*inpt) >>> print unzipped [(1, 2), (u'abc', u'def')] >>> print list(unzipped[0]) [1, 2]
Edit (@BradSolomon):
The above works for Python 2.x, where zip returns a list.
In Python 3.x, zip returns an iterator and the following is equivalent to the above:
>>> print(list(list(zip(*inpt))[0])) [1, 2]
Method 3
do you mean something like this?
new_list = [ seq[0] for seq in yourlist ]
What you actually have is a list of tuple objects, not a list of sets (as your original question implied). If it is actually a list of sets, then there is no first element because sets have no order.
Here I’ve created a flat list because generally that seems more useful than creating a list of 1 element tuples. However, you can easily create a list of 1 element tuples by just replacing seq[0] with (seq[0],).
Method 4
This is what operator.itemgetter is for.
>>> a = [(1, u'abc'), (2, u'def')] >>> import operator >>> b = map(operator.itemgetter(0), a) >>> b [1, 2]
The itemgetter statement returns a function that returns the element at the index that you specify. It’s exactly the same as writing
>>> b = map(lambda x: x[0], a)
But I find that itemgetter is a clearer and more explicit.
This is handy for making compact sort statements. For example,
>>> c = sorted(a, key=operator.itemgetter(0), reverse=True) >>> c [(2, u'def'), (1, u'abc')]
Method 5
I was thinking that it might be useful to compare the runtimes of the different approaches so I made a benchmark (using simple_benchmark library)
I) Benchmark having tuples with 2 elements

As you may expect to select the first element from tuples by index 0 shows to be the fastest solution very close to the unpacking solution by expecting exactly 2 values
import operator
import random
from simple_benchmark import BenchmarkBuilder
b = BenchmarkBuilder()
@b.add_function()
def rakesh_by_index(l):
return [i[0] for i in l]
@b.add_function()
def wayneSan_zip(l):
return list(list(zip(*l))[0])
@b.add_function()
def bcattle_itemgetter(l):
return list(map(operator.itemgetter(0), l))
@b.add_function()
def ssoler_upacking(l):
return [idx for idx, val in l]
@b.add_function()
def kederrack_unpacking(l):
return [f for f, *_ in l]
@b.add_arguments('Number of tuples')
def argument_provider():
for exp in range(2, 21):
size = 2**exp
yield size, [(random.choice(range(100)), random.choice(range(100))) for _ in range(size)]
r = b.run()
r.plot()
II) Benchmark having tuples with 2 or more elements

import operator
import random
from simple_benchmark import BenchmarkBuilder
b = BenchmarkBuilder()
@b.add_function()
def kederrack_unpacking(l):
return [f for f, *_ in l]
@b.add_function()
def rakesh_by_index(l):
return [i[0] for i in l]
@b.add_function()
def wayneSan_zip(l):
return list(list(zip(*l))[0])
@b.add_function()
def bcattle_itemgetter(l):
return list(map(operator.itemgetter(0), l))
@b.add_arguments('Number of tuples')
def argument_provider():
for exp in range(2, 21):
size = 2**exp
yield size, [tuple(random.choice(range(100)) for _
in range(random.choice(range(2, 100)))) for _ in range(size)]
from pylab import rcParams
rcParams['figure.figsize'] = 12, 7
r = b.run()
r.plot()
Method 6
You can use “tuple unpacking”:
>>> my_list = [(1, 'abc'), (2, 'def')] >>> my_ids = [idx for idx, val in my_list] >>> my_ids [1, 2]
At iteration time each tuple is unpacked and its values are set to the variables idx and val.
>>> x = (1, 'abc') >>> idx, val = x >>> idx 1 >>> val 'abc'
Method 7
if the tuples are unique then this can work
>>> a = [(1, u'abc'), (2, u'def')] >>> a [(1, u'abc'), (2, u'def')] >>> dict(a).keys() [1, 2] >>> dict(a).values() [u'abc', u'def'] >>>
Method 8
From a performance point of view, in python3.X
[i[0] for i in a]andlist(zip(*a))[0]are equivalent- they are faster than
list(map(operator.itemgetter(0), a))
Code
import timeit
iterations = 100000
init_time = timeit.timeit('''a = [(i, u'abc') for i in range(1000)]''', number=iterations)/iterations
print(timeit.timeit('''a = [(i, u'abc') for i in range(1000)]nb = [i[0] for i in a]''', number=iterations)/iterations - init_time)
print(timeit.timeit('''a = [(i, u'abc') for i in range(1000)]nb = list(zip(*a))[0]''', number=iterations)/iterations - init_time)
output
3.491014136001468e-05
3.422205176000717e-05
Method 9
when I ran (as suggested above):
>>> a = [(1, u'abc'), (2, u'def')] >>> import operator >>> b = map(operator.itemgetter(0), a) >>> b
instead of returning:
[1, 2]
I received this as the return:
<map at 0xb387eb8>
I found I had to use list():
>>> b = list(map(operator.itemgetter(0), a))
to successfully return a list using this suggestion. That said, I’m happy with this solution, thanks. (tested/run using Spyder, iPython console, Python v3.6)
Method 10
I wondered why nobody suggested to use numpy, but now after checking i understand. It is maybe not the best for mixed type arrays.
This would be a solution in numpy:
>>> import numpy as np >>> a = np.asarray([(1, u'abc'), (2, u'def')]) >>> a[:, 0].astype(int).tolist() [1, 2]
Method 11
To get an element of a list or tuple you can iterate through a list or tuple
a = [(1, u'abc'), (2, u'def')]
list1 = [a[i][0] for i in range(len(a))]
print(list1)
Method 12
you can unpack your tuples and get only the first element using a list comprehension:
l = [(1, u'abc'), (2, u'def')] [f for f, *_ in l]
output:
[1, 2]
this will work no matter how many elements you have in a tuple:
l = [(1, u'abc'), (2, u'def', 2, 4, 5, 6, 7)] [f for f, *_ in l]
output:
[1, 2]
Method 13
I’d prefer zipping this way:
>>> lst = [(1, u'abc'), (2, u'def')] >>> new, _ = zip(*lst) >>> new (1, 2) >>>
Or if you don’t know how many extra values there are:
>>> new, *_ = zip(*lst) >>> new (1, 2) >>>
Method 14
Those are tuples, not sets. You can do this:
l1 = [(1, u'abc'), (2, u'def')] l2 = [(tup[0],) for tup in l1] l2 >>> [(1,), (2,)]
Method 15
another simple suggestion if you need to convert to a nested of the tuple, and all elements inside the list the answer will be:
s=[]
for i in range(len(a)):
s.append(a[i][0])
print(s)
Output:
[(1),(2)]
Method 16
If you need to convert to a nested of the list, the answer will be:
a = [(1, u'abc'), (2, u'def')] print([list(i[0]) for i in a])
output:
[[1], [2]]
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0