jaq icon indicating copy to clipboard operation
jaq copied to clipboard

Support JQ's index/rindex function

Open John-Toohey opened this issue 1 year ago • 2 comments

Jq has the index and rindex functions which don't seem to be supported in jaq. Is there a specific reason for this? Thank you for your time.

John-Toohey avatar Jan 25 '24 20:01 John-Toohey

I don't think it's intentional. I'd even guess that anything from jq that's purposely excluded from jaq is documented in the README. For these filters (indices, index, rindex) you could just implement them in std. This is my attempt at it, using two auxiliary filters to deal with iterating over strings, and windowing:

# Indexing
def indices($i):
  def enumerate:
    . as $thing |
    if type == "string"
    then range(length) | [., $thing[.:.+1]]
    else range(length) | [., $thing[.]]
    end;

  def windowed($size):
    if $size <= 0 then empty
    else . as $array | range(length - $size + 1) | $array[.:. + $size]
    end;

  if ["string", "array"] | any(. == ($i | type))
  then [[windowed($i | length)] | enumerate | select(.[1] == $i)[0]]
  else [enumerate | select(.[1] == $i)[0]]
  end;

def index($i):  indices($i) | .[0];
def rindex($i): indices($i) | .[-1:][0];

It's not very good, and fails on ["a", "b", "c"] | indices("b") (mostly because of incomplete type dispatching), but it could be a start.

kklingenberg avatar Feb 03 '24 22:02 kklingenberg

I fixed the error by changing the condition to if ($i | type) == "array" or (type == "string" and ($i | type) == "string"), based on jq's implementation. Then I realized that jq gives special meaning to array as indices as in [1,2][[1,2]]. jaq doesn't allow that :thinking:. That is probably intentionally not supported :sweat_smile:

Anyway I put my implementation of these filters in a PR, with tests copied straight from jq's website: #158

kklingenberg avatar Feb 04 '24 01:02 kklingenberg