Nikolas Rieble
Nikolas Rieble

Reputation: 2601

Get elements from list using index from a list of arrays

Question:

I have a list of arrays such as:

a = [array([0, 4]), array([1, 3, 2])]

From another variable X, I want to take two subsets which are chosen by the index in each array in a.

X = [0.1, 0.7, 0.9, 0.2, 0.3] 

What I want to have is now:

result_1 = [0.1, 0.3]
result_2 = [0.7, 0.2, 0.9]

My solution would be to use a for loop such as:

def getresult(X, indices):
     result = []
     for i in indices:
          result.append(X[i])
     return result

This works fine:

getresult(X, a[0])
[0.1, 0.3]

My previous experience with programming suggest, that there is a much more beautiful and simple way to do so and that this is the place to ask. Preferably someone would know a solution that does not need looping.

Background/application:

Background: Crossvalidation for parameter optimization.

I have a list containing datapoints such as

X = [0.1, 0.7, 0.9, 0.2, 0.3]

Now I want to repeatedly take z samples out of that list (which actually is much bigger than this example). Therefore I create a new variable:

indices = np.arange(0,len(X),1)

HERE: [0, 1, 2, 3, 4]

Which then i shuffle and create nfold samples:

np.random.shuffle(indices)        
nfold_indices = np.array_split(indices,nfolds)

HERE with nfolds = 2: nfold_indices = [array([0, 4]), array([1, 3, 2])]

Upvotes: 0

Views: 144

Answers (3)

Moses Koledoye
Moses Koledoye

Reputation: 78546

Use a list comprehension, with a default for safety, in case an index from a is not in X:

a = [array('i', [0, 4]), array('i', [1, 3, 2])]
X = [0.1, 0.7, 0.9, 0.2, 0.3] 

result = [[(X[i:]+[0])[0] for i in o] for o in a]
#                  ^ default
# [[0.1, 0.3], [0.7, 0.2, 0.9]]

So in the event you have an arbitrary array containing an out of range index:

a = [array('i', [0, 4]), array('i', [1, 3, 20])]
#                                           ^ out of range
result = [[(X[i:]+[0])[0] for i in o] for o in a]
# [[0.1, 0.3], [0.7, 0.2, 0]]
#                         ^

Your code does not break

Upvotes: 0

Jblasco
Jblasco

Reputation: 3967

My first attempt, which basically follows your way of doing things in a more compact way would be:

result1, result2 = [ [X[ii] for ii in array] for array in a]

If you can be bothered to convert X to a numpy array, you can do:

X = np.array([ 0.1,  0.7,  0.9,  0.2,  0.3])
result1, result2 = X[a[0]], X[a[1]]

But this has the problem that it does not generalise well for more than a few arrays within a. Even if some people will hate me for using a lambda, another compact way of doing it that generalises better is:

results = map(lambda x: X[x], a)

Upvotes: 0

Neo
Neo

Reputation: 3786

return [X[i] for i in indices] would work.

Upvotes: 1

Related Questions