# Is there the equivalent to find all indexes for an Array Expression?

**URL:** <https://discuss.hail.is/t/is-there-the-equivalent-to-find-all-indexes-for-an-array-expression/1952>\
**Category:** Hail Query & hailctl\
**Created:** [March 11, 2021, 2:56am UTC](https://discuss.hail.is/t/is-there-the-equivalent-to-find-all-indexes-for-an-array-expression/1952 "2021-03-11T02:56:43Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![thondeboer](https://yyz2.discourse-cdn.com/flex036/user_avatar/discuss.hail.is/thondeboer/32/352_2.png) [@thondeboer](https://discuss.hail.is/u/thondeboer)\
**Post date:** [March 11, 2021, 2:56am UTC](https://discuss.hail.is/t/is-there-the-equivalent-to-find-all-indexes-for-an-array-expression/1952/1 "2021-03-11T02:56:43Z")

</div>

I was looking for something that will return me the indices (indexes?) for ALL members of an array, based on some arbitrary function…

A bit like how index returns the FIRST occurence of a value:

```
s3 = hl.literal(['Alice','Bob','Charlie'])
hl.eval(s3.index(lambda x: x.contains('l')))
0

```

The equivalent i would assume something like this

```
hl.eval(s3.all_index(lambda x: x.contains('l')))
[0, 2]

```

Am i missing something?

I went ahead and implemented it myself, since it was trivial once I found the code for index, but somehow I feel I am missing something obvious that is already there…

```
def all_index(self, x):
    """Returns the all indexes of `x`, or missing.

    Parameters
    ----------
    x : :class:`.Expression` or :obj:`typing.Callable`
        Value to find, or function from element to Boolean expression.

    Returns
    -------
    :class:`.ArrayExpression`

    Examples
    --------
    >>> hl.eval(names.all_index('Bob'))
    1

    >>> hl.eval(names.all_index('Beth'))
    None

    >>> hl.eval(names.all_index(lambda x: x.contains('l')))
    [0, 3]

    >>> hl.eval(names.all_index(lambda x: x.endswith('h')))
    None
    """
    if callable(x):
        def f(elt, x):
            return x(elt)
    else:
        def f(elt, x):
            return elt == x
    return hl.bind(lambda a: hl.range(0, a.length()).filter(lambda i: f(a[i], x)), self)

```

and then:

`hl.expr.expressions.typed_expressions.ArrayExpression.all_index = all_index`

---

<div class="post-metadata">

**Author:** ![tpoterba](https://yyz2.discourse-cdn.com/flex036/user_avatar/discuss.hail.is/tpoterba/32/61_2.png) [@tpoterba](https://discuss.hail.is/u/tpoterba)\
**Post date:** [March 11, 2021, 2:19pm UTC](https://discuss.hail.is/t/is-there-the-equivalent-to-find-all-indexes-for-an-array-expression/1952/2 "2021-03-11T14:19:11Z")

</div>

There’s no single function to do this, but quite easy to compose:

```auto
hl.enumerate(a)\
  .filter(lambda idx_and_element: filter_func(idx_and_element[1]))\
  .map(lambda idx_and_element: element[1])

```

---

<div class="post-metadata">

**Author:** ![thondeboer](https://yyz2.discourse-cdn.com/flex036/user_avatar/discuss.hail.is/thondeboer/32/352_2.png) [@thondeboer](https://discuss.hail.is/u/thondeboer)\
**Post date:** [March 11, 2021, 4:34pm UTC](https://discuss.hail.is/t/is-there-the-equivalent-to-find-all-indexes-for-an-array-expression/1952/3 "2021-03-11T16:34:04Z")

</div>

Ah…yeah, I was looking for a way to enumerate, since I figured something like that woudl be needed althoug I must have overlook it (may have something to do with the website help being a little broken, yesterday 🙂

How would you rate my implementation I provided wrs speed and scalability etc., compared to yours? Feels pretty similar although all\_index takes a function as a argument, so slightly more general, but maybe more costly?

---

<div class="post-metadata">

**Author:** ![tpoterba](https://yyz2.discourse-cdn.com/flex036/user_avatar/discuss.hail.is/tpoterba/32/61_2.png) [@tpoterba](https://discuss.hail.is/u/tpoterba)\
**Post date:** [March 11, 2021, 4:44pm UTC](https://discuss.hail.is/t/is-there-the-equivalent-to-find-all-indexes-for-an-array-expression/1952/4 "2021-03-11T16:44:59Z")

</div>

Should be identical, right now. At some point we’ll improve code generation of fused array operations such that my version will be a little faster in some cases (when `a` doesn’t need to be realized as an intermediate, just iterated over once), and then some point after that, we’ll improve our optimizer so your code generates the same thing as mine.
