This idea is similar to this one Adding the method find() to list, but I think it shouldn’t be limited to lists. Also, it can be more generic than “find first occurrence of x”, I often write small function just to loop through an iterable looking for a match with a more complex test.
"""This one is inspired from built-ins `any` and `all`
Edit: similar in behavior to
index = 0
for test in _iterable:
index += 1
def find2(predicate, _iterable):
"""This one is inspired from `map` and `filter`.
Note that in this version, the element could be
returned directly instead of returning the index.
for element in _iterable:
burger = ['bread', 'salad', 'steak', 'bread']
_example1 = find1(x is 'salad' for x in burger)
_example2 = find1(x.endswith('ad') for x in burger)
_example3 = find2(lambda x: x is 'salad', burger)
_example4 = find2(lambda x: x.endswith('ad'), burger)
_example5 = find2(isupper, burger)
I stopped counting the number of times I had to create a small function based on this model. It would be nice to have it as built-in.
Since the sequence must be stable for the index to be useful, why do you think a built-in function is more useful than
Personally, I have not run into needing this often enough to feel the need to have be a built-in (I have a need for
any() to return the true value it finds more than finding the index of something).
I’m not sold on the index thing. Most often, I only need the element itself, and retrieving it through the index feels inefficient. Should I have this option for the day I’ll need it? I don’t know.
And yes, my need comes from the fact that
any does not return the element matched. The function signature is not suited for that though, and it could deserve an update to look more like
filter. If this change happens, I’d consider this post obsolete.
Also, you made me realize that for lists I can do that
i = [x.endswith('ad') for x in burger].index(True)
e = burger[i]
But you have to admit the ugliness of this.
next(x for x in burger if x.endswith('ad')) do what you want in an efficient and elegant way?
That’s my usual solution, however the exception it raises when not found is
StopIteration with no message, which is unhelpful, so I always end up writing a small helper function to catch it and raise (a subclass of)
That’s smart. Thanks for sharing! I like it.