# Add a \`find()\` builtin function

**URL:** <https://discuss.python.org/t/add-a-find-builtin-function/13625>\
**Category:** Ideas\
**Tags:** builtins\
**Created:** [February 9, 2022, 4:33pm UTC](https://discuss.python.org/t/add-a-find-builtin-function/13625 "2022-02-09T16:33:22Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![TomBricaud](https://avatars.discourse-cdn.com/v4/letter/t/87869e/32.png) [@TomBricaud](https://discuss.python.org/u/TomBricaud)\
**Post date:** [February 9, 2022, 4:33pm UTC](https://discuss.python.org/t/add-a-find-builtin-function/13625/1 "2022-02-09T16:33:22Z")

</div>

This idea is similar to this one [Adding the method find() to list](https://discuss.python.org/t/adding-the-method-find-to-list/4113), 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.

Suggested implementations:

```python
def find1(_iterable):
  """This one is inspired from built-ins `any` and `all`
  Edit: similar in behavior to 
  `_iterable.index(True)`
  """
  index = 0
  for test in _iterable:
    if test:
      return index
    index += 1
  return None

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:
    if predicate(element):
      return element
  return None

```

Usage examples:

```auto
burger = ['bread', 'salad', 'steak', 'bread']

# find1
_example1 = find1(x is 'salad' for x in burger)
_example2 = find1(x.endswith('ad') for x in burger)

# find2
_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.

---

<div class="post-metadata">

**Author:** ![brettcannon](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/brettcannon/32/34895_2.png) [@brettcannon](https://discuss.python.org/u/brettcannon)\
**Post date:** [February 9, 2022, 8:34pm UTC](https://discuss.python.org/t/add-a-find-builtin-function/13625/2 "2022-02-09T20:34:30Z")

</div>

Since the sequence must be stable for the index to be useful, why do you think a built-in function is more useful than `list(iterable).index()`?

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).

---

<div class="post-metadata">

**Author:** ![TomBricaud](https://avatars.discourse-cdn.com/v4/letter/t/87869e/32.png) [@TomBricaud](https://discuss.python.org/u/TomBricaud)\
**Post date:** [February 9, 2022, 10:40pm UTC](https://discuss.python.org/t/add-a-find-builtin-function/13625/3 "2022-02-09T22:40:33Z")

</div>

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

```python
i = [x.endswith('ad') for x in burger].index(True)
e = burger[i]

```

But you have to admit the ugliness of this.

---

<div class="post-metadata">

**Author:** ![daniele](https://avatars.discourse-cdn.com/v4/letter/d/dfb087/32.png) [@daniele](https://discuss.python.org/u/daniele)\
**Post date:** [February 10, 2022, 11:20pm UTC](https://discuss.python.org/t/add-a-find-builtin-function/13625/4 "2022-02-10T23:20:37Z")

</div>

Doesn’t `next(x for x in burger if x.endswith('ad'))` do what you want in an efficient and elegant way?

---

<div class="post-metadata">

**Author:** ![EpicWink](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/epicwink/32/17968_2.png) [@EpicWink](https://discuss.python.org/u/EpicWink)\
**Post date:** [February 10, 2022, 11:32pm UTC](https://discuss.python.org/t/add-a-find-builtin-function/13625/5 "2022-02-10T23:32:27Z")

</div>

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) `LookupError`

---

<div class="post-metadata">

**Author:** ![TomBricaud](https://avatars.discourse-cdn.com/v4/letter/t/87869e/32.png) [@TomBricaud](https://discuss.python.org/u/TomBricaud)\
**Post date:** [February 11, 2022, 6:36am UTC](https://discuss.python.org/t/add-a-find-builtin-function/13625/6 "2022-02-11T06:36:18Z")

</div>

That’s smart. Thanks for sharing! I like it.
