neverendingqs
neverendingqs

Reputation: 4276

What is a pythonic of finding the indices of the first value in a multi-dimensional list that matches the value I'm looking for?

I have a 2D list that has either True or False in it (although I'm also interested in non-boolean values). I want to know the first True value that appears in this list as a tuple.

For example [[False, False], [True, False]] returns (1, 0).

This is the non-pythonic code I have

for x in range(0, width):
    for y in range(0, height):
        if allFood[x][y]:
            return (x, y)

Upvotes: 0

Views: 53

Answers (6)

ely
ely

Reputation: 77424

While there is no need to necessarily use NumPy for this, it is nonethless a very good choice, especially if this indicates broader use of multidimensional arrays in your application.

In [14]: map(tuple, np.argwhere([[False, False], [True, False]]))[0]
Out[14]: (1, 0)

Upvotes: 1

Saksham Varma
Saksham Varma

Reputation: 2130

Use list comprehensions:

def f():
    mat = [[False, False], [True, False]]
    return [(ind1, ind2) for ind1, sublist in enumerate(mat) for ind2, elem in
     enumerate(sublist) if elem is True][0]

Upvotes: 0

FMc
FMc

Reputation: 42411

I would keep your current code as it is. But if you're looking for something with list comprehensions, generators, and so forth, you can create a generator (g) that basically does the same thing as your current code and then return the first value from it. For example:

# Example data.
xs = [[0,0,1,1], [1,0], [0,1,0]]

g = ((i, j) for i, ys in enumerate(xs) for j, y in enumerate(ys) if y)
return next(g, None)  # (0, 2)

Upvotes: 1

Sarith Subramaniam
Sarith Subramaniam

Reputation: 246

I think this function should work for nested lists of any size.

def ret_tup(lst):

  #Get the index of the first nested list which has a true value.   
  truthidx =([any(value) for value in lst]).index(True)

  #Return the tuple as 0 and 1   
  return tuple({True:1,False:0}[value] for value in lst[truthidx])

##Examples  
a =[[False,False],[False,False],[True,True]]
print (ret_tup(a)) #Returns (1,1)

b = [[False,False,False],[False,False,False],[False,False],  [True,False,True,False]]
print(ret_tup(b)) #Returns (1,0,1,0)

Upvotes: 0

jedwards
jedwards

Reputation: 30210

Your code is probably most directly mapped to a method using itertools.product

import itertools
def func(<...>):
    for (x,y) in itertools.product(xrange(width), xrange(height)):
        if allFood[x][y]: return (x,y)

But I'm not sure it's necessary, it increases the complexity (if you don't know about itertools), and increases the character count.

Upvotes: 0

Avinash Raj
Avinash Raj

Reputation: 174696

Seems like you want something like this,

>>> l = [[False, False], [True, False]]
>>> [1 if j is True else 0  for i in l for j in i if True in i]
[1, 0]
>>> [1 if j  else 0  for i in l for j in i if True in i]
[1, 0]

Upvotes: 0

Related Questions