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