Is It Possible To Index Nested Lists Using Tuples In Python?
Solution 1:
If you really want to use tuples for indexing you can implement your own class that extends list
and redefines __getattr__
to work with tuples and use that:
class TList(list):
def __getitem__(self, index):
if hasattr(index, "__iter__"):
# index is list-like, traverse downwards
item = self
for i in index:
item = item[i]
return item
# index is not list-like, let list.__getitem__ handle it
return super().__getitem__(index)
elements = TList([ [ 'a', 'b', 'c'],
[ 'c', 'd', 'e'],
[ 'f', 'g', 'h'] ])
index = ( (0,0), (0,2), (2,0), (2,2) )
for i in index:
print(elements[i])
a
c
f
h
Solution 2:
Yes, you can do that. I wrote a similar example:
index = [ [0,0], [0,2], [2,0], [2,2] ]
elements = [ [ 'a', 'b', 'c'],
[ 'c', 'd', 'e'],
[ 'f', 'g', 'h'] ]
for i,j in index:
print (elements [ i ] [ j ])
a c f h
Solution 3:
# I would like to do this:
# print(elements[i])
No you cannot index a specific value of a nested list in this way.
The only slightly better way would be to "unpack" the tuples are you're iterating over them:
Example:
for i, j in index:
print(elements[i][j])
See: Tuples ans Sequences
Solution 4:
If you want to print everything in elements
index = ( (0,0), (0,2), (2,0), (2,2) )
elements = [ [ 'a', 'b', 'c'],
[ 'c', 'd', 'e'],
[ 'f', 'g', 'h'] ]
for row in elements:
for i in range(len(row)):
print (row[i])
Solution 5:
Here are some answers that work without knowing the dimension in advance.
A recursive version:
def multiget_rec(arr, *indices):
if len(indices)==0:
return arr
return multiget_rec(arr[indices[0]], *indices[1:])
A procedural version:
def multiget_proc(arr, *indices):
while len(indices)>0:
i, *indices = indices
arr = arr[i]
return arr
And a version based on reduce which could be used as a 1-liner:
from functools import reduce
def multiget_reduce(arr, *indices):
return reduce(lambda a,i:a[i], indices, arr)
All can be called like
for i in index:
print (multiget(elements, *i))
Edit:
Using reduce seems to be the fastest of the three methods, at least for small arrays. I also think it looks the cleanest.
$ python -m timeit -s "def multiget_rec(arr, *indices):" \
-s " if len(indices)==0: return arr" \
-s " return multiget_rec(arr[indices[0]], *indices[1:])" \
-- "d = [[[3]]]" \
"multiget_rec(d, 0,0,0)"
500000 loops, best of 5: 941 nsec per loop
$ python -m timeit -s "def multiget_proc(arr, *indices):" \
-s " while len(indices)>0:" \
-s " i, *indices = indices" \
-s " return arr" \
-s "d = [[[3]]]" \
-- "multiget_proc(d, 0,0,0)"
500000 loops, best of 5: 529 nsec per loop
$ python -m timeit -s "from functools import reduce" \
-s "def multiget_reduce(arr, *indices):" \
-s " return reduce(lambda a,i:a[i], indices, arr)" \
-s "d = [[[3]]]" \
-- "multiget_reduce(d, 0,0,0)"
1000000 loops, best of 5: 384 nsec per loop
Post a Comment for "Is It Possible To Index Nested Lists Using Tuples In Python?"