53

I'm sure there's a nice way to do this in Python, but I'm pretty new to the language, so forgive me if this is an easy one!

I have a list, and I'd like to pick out certain values from that list. The values I want to pick out are the ones whose indexes in the list are specified in another list.

For example:

indexes = [2, 4, 5]
main_list = [0, 1, 9, 3, 2, 6, 1, 9, 8]

the output would be:

[9, 2, 6]

(i.e., the elements with indexes 2, 4 and 5 from main_list).

I have a feeling this should be doable using something like list comprehensions, but I can't figure it out (in particular, I can't figure out how to access the index of an item when using a list comprehension).

Timur Shtatland
  • 12,024
  • 2
  • 30
  • 47
Ben
  • 66,838
  • 37
  • 84
  • 108

8 Answers8

123
[main_list[x] for x in indexes]

This will return a list of the objects, using a list comprehension.

Matthew Schinckel
  • 35,041
  • 6
  • 86
  • 121
4
t = []
for i in indexes:
    t.append(main_list[i])
return t
Yuval Adam
  • 161,610
  • 92
  • 305
  • 395
  • 1
    While this is less elegant than a list comprehension, I like it better as an answer for someone completely new to Python. –  Apr 07 '09 at 09:56
2

If you're good with numpy:

import numpy as np
main_array = np.array(main_list) # converting to numpy array
out_array = main_array.take([2, 4, 5])
out_list = out_array.tolist() # if you want a list specifically
mathfux
  • 5,759
  • 1
  • 14
  • 34
2
map(lambda x:main_list[x],indexes)
Thor
  • 45,082
  • 11
  • 119
  • 130
1

As an alternative to a list comprehension, you can use map with list.__getitem__. For large lists you should see better performance:

import random

n = 10**7
L = list(range(n))
idx = random.sample(range(n), int(n/10))

x = [L[x] for x in idx]
y = list(map(L.__getitem__, idx))

assert all(i==j for i, j in zip(x, y))

%timeit [L[x] for x in idx]            # 474 ms per loop
%timeit list(map(L.__getitem__, idx))  # 417 ms per loop

For a lazy iterator, you can just use map(L.__getitem__, idx). Note in Python 2.7, map returns a list, so there is no need to pass to list.

jpp
  • 159,742
  • 34
  • 281
  • 339
1

I think Yuval A's solution is a pretty clear and simple. But if you actually want a one line list comprehension:

[e for i, e in enumerate(main_list) if i in indexes]
0

I have noticed that there are two optional ways to do this job, either by loop or by turning to np.array. Then I test the time needed by these two methods, the result shows that when dataset is large
【[main_list[x] for x in indexes]】is about 3~5 times faster than 【np.array.take()】
if your code is sensitive to the computation time, the highest voted answer is a good choice.

Xuemin Chi
  • 21
  • 3
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/31561306) – buhtz Apr 21 '22 at 08:13
  • 1
    Okay, Thank you very much! I will be more careful in commenting! – Xuemin Chi Apr 21 '22 at 14:25
0
indexes = [2, 4, 5]
main_list = [0, 1, 9, 3, 2, 6, 1, 9, 8]
l=[] # create a blank new list
for index,value in enumerate(indexes):
    #append values to the new list
    l.append(main_list[value])
print(l) # output [9, 2, 6]