187

I'm wondering what is the best way to extract the first item of each sublist in a list of lists and append it to a new list. So if I have:

lst = [[a,b,c], [1,2,3], [x,y,z]]

And, I want to pull out a, 1 and x and create a separate list from those.

I tried:

lst2.append(x[0] for x in lst)
2

9 Answers 9

255

Using list comprehension:

>>> lst = [['a','b','c'], [1,2,3], ['x','y','z']]
>>> lst2 = [item[0] for item in lst]
>>> lst2
['a', 1, 'x']
2
  • 2
    List comprehension method is also the fastest, even faster than Numpy method. jboi's answer talks about performance comparison,
    – Qiao Zhang
    Commented Jul 16, 2018 at 3:22
  • 1
    @QiaoZhang: numpy is slower if you have to convert to a numpy array in the first place. If the data is stored as a numpy array from the get-go, it'll be much faster. Commented Sep 15, 2021 at 2:30
105

You could use zip:

>>> lst=[[1,2,3],[11,12,13],[21,22,23]]
>>> zip(*lst)[0]
(1, 11, 21)

Or, Python 3 where zip does not produce a list:

>>> list(zip(*lst))[0]
(1, 11, 21)

Or,

>>> next(zip(*lst))
(1, 11, 21)

Or, (my favorite) use numpy:

>>> import numpy as np
>>> a=np.array([[1,2,3],[11,12,13],[21,22,23]])
>>> a
array([[ 1,  2,  3],
       [11, 12, 13],
       [21, 22, 23]])
>>> a[:,0]
array([ 1, 11, 21])
2
  • Have not downvoted but the first code snippet (the zip) produces: "'zip' object is not subscriptable". Python 3.6 on Jupyter.
    – jboi
    Commented Jan 7, 2018 at 12:19
  • @jboi: Just wrap list around it first or use next. Thanks
    – dawg
    Commented Jan 7, 2018 at 15:32
33

Had the same issue and got curious about the performance of each solution.

Here's is the %timeit:

import numpy as np
lst = [['a','b','c'], [1,2,3], ['x','y','z']]

The first numpy-way, transforming the array:

%timeit list(np.array(lst).T[0])
4.9 µs ± 163 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

Fully native using list comprehension (as explained by @alecxe):

%timeit [item[0] for item in lst]
379 ns ± 23.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Another native way using zip (as explained by @dawg):

%timeit list(zip(*lst))[0]
585 ns ± 7.26 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Second numpy-way. Also explained by @dawg:

%timeit list(np.array(lst)[:,0])
4.95 µs ± 179 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

Surprisingly (well, at least for me) the native way using list comprehension is the fastest and about 10x faster than the numpy-way. Running the two numpy-ways without the final list saves about one µs which is still in the 10x difference.

Note that, when I surrounded each code snippet with a call to len, to ensure that Generators run till the end, the timing stayed the same.

3
  • 6
    there's a substantial overhead when creating an array.
    – hpaulj
    Commented Aug 28, 2018 at 3:12
  • 2
    agree with hpaulj, if you start off with numpy array, [:,0] is faster. Give it a go: lst = np.array([['a','b','c'], [1,2,3], ['x','y','z']]), then lst[:,0]. The conversion in the example time trials gives list comprehension an unfair advantage. So if you can, use a numpy array to store your data if speed is your ultimate goal. Numpy is almost always faster. It's built for speed. Commented Nov 14, 2018 at 20:13
  • Thanks for sharing. I'm curious about %timeit, is this something magic from python? I mean %timeit is not standard python isn't it? Thanks!
    – Dan.py
    Commented Nov 23, 2022 at 16:05
16

Python includes a function called itemgetter to return the item at a specific index in a list:

from operator import itemgetter

Pass the itemgetter() function the index of the item you want to retrieve. To retrieve the first item, you would use itemgetter(0). The important thing to understand is that itemgetter(0) itself returns a function. If you pass a list to that function, you get the specific item:

itemgetter(0)([10, 20, 30]) # Returns 10

This is useful when you combine it with map(), which takes a function as its first argument, and a list (or any other iterable) as the second argument. It returns the result of calling the function on each object in the iterable:

my_list = [['a', 'b', 'c'], [1, 2, 3], ['x', 'y', 'z']]
list(map(itemgetter(0), my_list)) # Returns ['a', 1, 'x']

Note that map() returns a generator, so the result is passed to list() to get an actual list. In summary, your task could be done like this:

lst2.append(list(map(itemgetter(0), lst)))

This is an alternative method to using a list comprehension, and which method to choose highly depends on context, readability, and preference.

More info: https://docs.python.org/3/library/operator.html#operator.itemgetter

2
  • Any idea how that compares performance-wise to list comprehensions?
    – Konstantin
    Commented Oct 26, 2020 at 10:28
  • Python's timeit module can check your specific code case (docs.python.org/3/library/timeit.html), List comprehensions are generally more performant. I ran timeit on a list containing 100,000 lists with the interior lists two items in length, and iterated the timeit test 10,000 times. List comprehensions took 25.2 seconds and itemgetter took 28.8 seconds. I personally find itemgetter useful in some contexts where performance isn't as important but where it happens to produce easier to read code. Commented Oct 27, 2020 at 22:37
2

Your code is almost correct. The only issue is the usage of list comprehension.

If you use like: (x[0] for x in lst), it returns a generator object. If you use like: [x[0] for x in lst], it return a list.

When you append the list comprehension output to a list, the output of list comprehension is the single element of the list.

lst = [["a","b","c"], [1,2,3], ["x","y","z"]]
lst2 = []
lst2.append([x[0] for x in lst])
print lst2[0]

lst2 = [['a', 1, 'x']]

lst2[0] = ['a', 1, 'x']

Please let me know if I am incorrect.

1
lst = [['a','b','c'], [1,2,3], ['x','y','z']]
outputlist = []
for values in lst:
    outputlist.append(values[0])

print(outputlist) 

Output: ['a', 1, 'x']

0
0

You said that you have an existing list. So I'll go with that.

>>> lst1 = [['a','b','c'], [1,2,3], ['x','y','z']]
>>> lst2 = [1, 2, 3]

Right now you are appending the generator object to your second list.

>>> lst2.append(item[0] for item in lst)
>>> lst2
[1, 2, 3, <generator object <genexpr> at 0xb74b3554>]

But you probably want it to be a list of first items

>>> lst2.append([item[0] for item in lst])
>>> lst2
[1, 2, 3, ['a', 1, 'x']]

Now we appended the list of first items to the existing list. If you'd like to add the items themeselves, not a list of them, to the existing ones, you'd use list.extend. In that case we don't have to worry about adding a generator, because extend will use that generator to add each item it gets from there, to extend the current list.

>>> lst2.extend(item[0] for item in lst)
>>> lst2
[1, 2, 3, 'a', 1, 'x']

or

>>> lst2 + [x[0] for x in lst]
[1, 2, 3, 'a', 1, 'x']
>>> lst2
[1, 2, 3]

https://docs.python.org/3.4/tutorial/datastructures.html#more-on-lists https://docs.python.org/3.4/tutorial/datastructures.html#list-comprehensions

1
  • 1
    Your answer is nice and complete for what it sounds like the OP wants, but I think the word append in the question is causing confusion. It sounds like s/he simply wants the list comprehension portion of your solution.
    – beroe
    Commented Jul 31, 2014 at 6:21
0

You can extract the 1st value from a list of lists to a new list as shown below:

list_of_lists = [
    ['John', 'Anna'], [36, 24], ['Male', 'Female']
] 
           
new_list = [list[0] for list in list_of_lists] # Here

print(new_list) # ['John', 36, 'Male']

Or:

list_of_lists = [
    ['John', 'Anna'], [36, 24], ['Male', 'Female']
] 
           
new_list = [first for [first, second] in list_of_lists] # Here

print(new_list) # ['John', 36, 'Male']
-2

The other answer I could suggest is

lst = [['a','b','c'], [1,2,3], ['x','y','z']]
new_lst=[lst[0][0],lst[1][0],lst[2][0]]
print(new_lst)

The output comes as follows

['a', 1, 'x']

Hope this helps! Thanks!

Not the answer you're looking for? Browse other questions tagged or ask your own question.