2

Suppose we have two lists

list_A = [1,3,4,54,3,5,6,2,6,77,73,39]
list_B = [0,3,2,8]

I want to access elements of list_A that have the values in list_B as their indices (without using loops).

After implementing it, the result should be as follows for the above case:

[1, 54, 4, 6]

Is there any easy method to do this without bothering with for loops (calling it explicitly in the code) ?

2
  • Slightly related if you're going the numpy path: stackoverflow.com/questions/7002895/numpy-array-indexing Commented Mar 30, 2013 at 17:07
  • It all depends on what you mean by a for-loop. The obvious way to do it is with a list comprehension. Does [A[x] for x in B] use a for-loop? Maybe. Does map(lambda i: list_A[i], list_B)? No for-loop in sight, but there is iteration in map. How about numpy solutions? No iteration visible, but ... Commented Mar 30, 2013 at 17:24

5 Answers 5

8

Everything will use a loop internally*, but it doesn't have to be as complicated as you might think. You can try a list comprehension:

[list_A[i] for i in list_B]

Alternatively, you could use operator.itemgetter:

list(operator.itemgetter(*list_B)(list_A))

>>> import operator
>>> list_A = [1,3,4,54,3,5,6,2,6,77,73,39]
>>> list_B = [0,3,2,8]
>>> [list_A[i] for i in list_B]
[1, 54, 4, 6]
>>> list(operator.itemgetter(*list_B)(list_A))
[1, 54, 4, 6]

* OK! Maybe you don't need a loop with recursion, but I think it's definately overkill for something like this.

Sign up to request clarification or add additional context in comments.

5 Comments

Which uses a loop. But the requirement that you don't use a loop is insane.
@MartijnPieters Everything will, at its core, use a loop.
@A.R.S.: Of course, the numpy solutions use loops too, internally. As I said, the stated requirement is not attainable.
My intention is not to call a loop explicitly. Thank you.
@A.R.S.: "...unless it uses recursion."
3

Recursion answer

No iteration/loops here. Just recursion.

>>> list_A = [1,3,4,54,3,5,6,2,6,77,73,39]
>>> list_B = [0,3,2,8]
>>> def foo(src, indexer):
...     if not indexer:
...         return []
...     else:
...         left, right = indexer[0], indexer[1:]
...         return [src[left]] + foo(src, right)
... 
>>> foo(list_A, list_B)
[1, 54, 4, 6]

Comments

2

If you're using numpy, you can do the following:

list_A[list_B]  // yields [1, 54, 4, 6]

Edit: As Nick T pointed out, don't forget to convert to arrays first!

2 Comments

Lists should be converted to arrays before doing this, right?
list_A should be. list_B doesn't have to be. arr_A = np.array(list_A)
2

map answer

>>> list_A = [1,3,4,54,3,5,6,2,6,77,73,39]
>>> list_B = [0,3,2,8]
>>> map(lambda i: list_A[i], list_B)
[1, 54, 4, 6]

Disclaimer

I don't think this technically meets the requirement that there be no for-loop.

Comments

1

Numpy can do this with its indexing in a fairly straightforward manner. Convert the list to an array then you're gold. You can pass any sort of iterable as indices.

>>> import numpy
>>> list_A = [1,3,4,54,3,5,6,2,6,77,73,39]
>>> list_B = [0,3,2,8]
>>> numpy.array(list_A)[list_B]
array([ 1, 54,  4,  6])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.