I have a list of lists:
colours = [["#660000","#863030","#ba4a4a","#de7e7e","#ffaaaa"],["#a34b00","#d46200","#ff7a04","#ff9b42","#fec28d"],["#dfd248","#fff224","#eefd5d","#f5ff92","#f9ffbf"],["#006600","#308630","#4aba4a","#7ede7e","#aaffaa"]]
What's the cleanest way of searching the list and returning the position of one of the items, e.g. "#660000"
?
I have looked at the index
method, but that doesn't seem to unpack the list inside the list.
postion = colours.index("#660000")
gives: ValueError: ['#660000'] is not in list
, not [0][0]
as I expect...
To find the (row, column) index pair of an element in a list of lists, iterate over the rows and their indices using the enumerate() function and use the row. index(x) method to determine the index of element x in the row .
To find the index of an element in a list, you use the index() function. It returns 3 as expected. However, if you attempt to find an element that doesn't exist in the list using the index() function, you'll get an error.
To find an element in the list, use the Python list index() method, The index() is an inbuilt Python method that searches for an item in the list and returns its index. The index() method finds the given element in the list and returns its position.
By using type() operator we can get the string elements indexes from the list, string elements will come under str() type, so we iterate through the entire list with for loop and return the index which is of type string.
I'd do something like this:
[(i, colour.index(c))
for i, colour in enumerate(colours)
if c in colour]
This will return a list of tuples where the first index is the position in the first list and second index the position in the second list (note: c
is the colour you're looking for, that is, "#660000"
).
For the example in the question, the returned value is:
[(0, 0)]
If you just need to find the first position in which the colour is found in a lazy way you can use this:
next(((i, colour.index(c))
for i, colour in enumerate(colours)
if c in colour),
None)
This will return the tuple for the first element found or None
if no element is found (you can also remove the None
argument above in it will raise a StopIteration
exception if no element is found).
Edit: As @RikPoggi correctly points out, if the number of matches is high, this will introduce some overhead because colour
is iterated twice to find c
. I assumed this to be reasonable for a low number of matches and to have an answer into a single expression. However, to avoid this, you can also define a method using the same idea as follows:
def find(c):
for i, colour in enumerate(colours):
try:
j = colour.index(c)
except ValueError:
continue
yield i, j
matches = [match for match in find('#660000')]
Note that since find
is a generator you can actually use it as in the example above with next
to stop at the first match and skip looking further.
Using enumerate()
you could write a function like this one:
def find(target):
for i,lst in enumerate(colours):
for j,color in enumerate(lst):
if color == "#660000":
return (i, j)
return (None, None)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With