-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
def last: #2850
base: master
Are you sure you want to change the base?
def last: #2850
Conversation
I'd like you to share your future plan to make pick/1 work well with any paths. Thanks. |
Right, so we can make |
I have no objections to not supporting negative indices. There is currently no named def for .[length-2] but if there were, it would work, so I don’t see any issue there. If someone wants the penultimate item, they can write pick( .[length-2] ), etc. |
Here's an ugly, sub-optimal def keep(ps):
([norm(path(ps))]|sort) as $ps
| ([norm(path(..))|$ps[] as $p|select(not(prefix($p; .)))]|sort) as $aps
| delpaths(($aps - $ps)); I'll share |
I'm sharing some observations; considering
and constant paths are pure i.e.
but when setting a path against different values,
|
@itchyny yes, the issue is |
That's certainly an option. But jq is a fairly elegant language, so it'd be nice to support negative indices here. |
Seems... wrong. I expected |
OK, finally path normalization code I can share. The idea is to take an array or object and a path (as output by (This is still not very pretty. We can optimize for elegance later.) # Normalizes negative indices in `$p` relative to `.`
def norm($p):
def type($x): $x|type;
def length($x): $x|length;
# `$p` here is of the form `[<number>, ...]`.
# `.` here is an array that `$p` is a path in
#
# Outputs `$p` with `$p[0]` normalized.
def norm_idx($p):
if $p[0] < 0 then [$p[0] + length] + $p[1:] else $p end;
# `$p` here is of the form `[{start: ..., end: ...}, ...]`.
# `.` here is an array that `$p` is a path in
#
# Outputs `$p` with `$p[0] normalized
def norm_slice($p):
length as $len
|(if $p[0].start < 0
then
[$p[0].start + $len, $p[0].end]
else $p
end) as $p
|(if $p[0].end < 0
then
[$p[0].start, $p[0].end + $len]
else $p
end);
# Main body of `norm/1`
(if length($p) == 0
# $p == [], nothing to do
then $p
elif type($p[0]) == "object"
# Normalize slice indices
then
norm_slice($p) as $p
| if length($p) == 1
then [range($p.start; $p.end)]
elif type($p[1]) != "number"
then "Array slice index must be numeric" | error
elif $p[1] < 0
then [$p[0] + $p[1] + ($p.end - $p.start)] + $p[2:]
else
[$p[0].start + $p[1]] + $p[2:]
end
elif type($p[0]) == "number"
# Normalize negative array indices
then
norm_idx($p)
# No normalization needed for object keys
else $p
end) as $p
| if length($p) <= 1
then $p
else
[$p[0]] + (getpath($p[0:1]) | norm($p[1:]))
end
;
def keep(ps):
def prefix($a; $b):
def min($a; $b):
if $a < $b
then $a
else $b
end;
min($a|length; $b|length) as $l
| $a[0:$l] == $b[0:$l];
def not($x): $x|not;
([norm(path(ps))]|sort) as $ps
| ([norm(path(..))|$ps[] as $p|select(not(prefix($p; .)))]|sort) as $aps
| delpaths(($aps - $ps)); |
@pkoppstein please check if you can make |
@nicowilliams wrote:
I will do so, but for 1.7, I am inclined to think it would be sufficient to tweak the def of There are two reasons for my reservations about aiming higher for 1.7: |
jq.1.prebuilt
Outdated
@@ -1,3 +1,4 @@ | |||
pipenv run python validate_manual_schema.py content/manual/manual.yml |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Accidentally added line?
rm auto-inserted spurious pipenv line
@wader wrote:
It was added by I removed it manually. Thanks. |
def last: .[length-1]
This is sufficient to ensure that
pick(last)
works in the obvious way, as it did before some recent updates.