On Fri, May 22, 2020 at 06:37:11PM -0700, Ethan Furman wrote: > On 05/22/2020 05:11 PM, David Mertz wrote: > >On 05/22/2020 04:43 AM, Steven D'Aprano wrote: > > >> i = somelist.index(needle, pred=comparison) > > >Why not just this (by object, not by its index, but that seems simpler): > > > > >>> do_something(next(filter(pred, somelist))) > > Something about 55 > > >>> somelist > > [3, 4, 29, 23, 46, 55, 90, 81] > > >>> pred > > <function div5 at 0x7fd10794ee50> > > Steven, using David's example list, what would `needle` and `comparison` be > in your proposal?
Good question! Thank you for pushing me to think about this a little harder. I read David's example as "first item that is divisible by 5" so the predicate would be rubbish: # I can never remember if the needle comes first or second... somelist.index(0, pred=lambda a, b: a%5 == b) somelist.index(0, pred=lambda a, b: b%5 == a) Yuck. So I think I have the wrong mental model here. Going back to the thread on discuss that inspired the question, I think a *key function* is probably better: for index, blwr in enumerate(blowers): if blwr.id_ == value: print(index) break # becomes blowers.index(value, key=operator.attrgetter('id_')) # or if you prefer blowers.index(value, key=lambda obj: obj.id_) although I expect the attrgetter version may be faster, for those who care about such things. With a key function, David's example becomes: somelist.index(0, key=lambda n: n%5) Here are a few more possibilities. # number not divisible by 5 somelist.index(True, key=lambda x: bool(x%5)) # case-insensitive search somelist.index('spam', key=str.casefold) # number less than 0 somelist.index(True, key=lambda x: x<0) # item of length exactly 2 somelist.index(2, key=len) # identity search somelist.index(True, key=lambda obj: obj is someobj) # find a non-NAN somelist.index(False, key=math.isnan) # find a particular user somelist.index('guido', key=lambda user: user.name) # instance of a class somelist.index(MyClass, key=type) # doesn't match subclasses # does match subclasses somelist.index(True, key=lambda obj: isinstance(obj, MyClass)) # z-coordinate of a 3D point equals -7 somelist.index(-7, key=lambda point: point[2]) # sum of values in the item equals 99 somelist.index(99, key=sum) # sum of sales for the month is greater than 1000 somelist.index(True, key=lambda x: sum(x.sales() > 1000)) Obviously not all such key functions are that simple and you may need to write a helper function, but the same applies to filter. Some of these examples are a little artificial, in that you might want *all* of the items that match, not just the first. In that case, a filter function is probably better. Or you could loop, adjusting the start index each time. But if you do want only the first matching value, or if you know that there is only one such value, then a key function is more obvious than calling next and filter. -- Steven _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/IVPAOSLKVJTBU367CMA6W2YT3BT7JQ5D/ Code of Conduct: http://python.org/psf/codeofconduct/