用范围替换数组中的连续整数
Replace consecutive integers in an array with ranges
我想将连续的整数合并到一个排序数组中,并使用 jq
将它们替换为范围。
示例 1
input: [1,2,3,4,6,98,99,101]
desired output: "1-4,6,98-99,101"
示例 2
input: [1,3,5]
desired output: "1,3,5"
示例 3
input: [1,2,3,4,5]
desired output: "1-5"
我找到了一个使用 foreach
的解决方案,但它对我来说似乎不是很优雅和紧凑。
这个任务有更简单的解决方案吗?
[foreach (.[], 99999) as $current
({};
if length == 0 then
{first: $current}
elif (has("last") | not) and .first + 1 != $current then
{first: $current, extract: "\(.first)"}
elif has("last") and .last + 1 != $current then
{first: $current, extract: "\(.first)-\(.last)"}
else
{first, last: $current}
end;
.extract // empty
)]
| join(",")
我会分两步完成。
首先,分组到范围内。
reduce .[] as $_ (
[];
if $_ - 1 == .[-1][1] then
.[-1][1] = $_
else
. + [ [ $_, $_ ] ]
end
)
此步骤生成 [[1,1],[2,4],[6,6],[98,99],[101,101]]
。
然后,构建字符串。
map(
if .[0] == .[1] then
"\( .[0] )"
else
"\( .[0] )-\( .[1] )"
end
) |
join(",")
Demo 在 jqplay
它并没有短多少,但我认为它更简单、更清晰。
此外,分离关注点不仅对简单性和清晰性有好处。您可以选择将代码隐藏在两个小函数中。您可以更轻松地自定义输出,比如为 [98,99]
生成 98,99
而不是 98-99
。您甚至可以决定重用根本不需要生成字符串的代码。
但最重要的是,此解决方案消除了魔法 99999
!
这是另一个解决方案:
reduce .[1:][] as $n ([.[:1]];
if $n == .[-1][-1] + 1 then .[-1][1] = $n else . + [[$n]] end
) | map(join("-")) | join(",")
喂食时
[1,2,3,4,6,98,99,101]
[1,3,5]
[1,2,3,4,5]
[4]
[]
它输出
"1-4,6,98-99,101"
"1,3,5"
"1-5"
"4"
""
我想将连续的整数合并到一个排序数组中,并使用 jq
将它们替换为范围。
示例 1
input:
[1,2,3,4,6,98,99,101]
desired output:"1-4,6,98-99,101"
示例 2
input:
[1,3,5]
desired output:"1,3,5"
示例 3
input:
[1,2,3,4,5]
desired output:"1-5"
我找到了一个使用 foreach
的解决方案,但它对我来说似乎不是很优雅和紧凑。
这个任务有更简单的解决方案吗?
[foreach (.[], 99999) as $current
({};
if length == 0 then
{first: $current}
elif (has("last") | not) and .first + 1 != $current then
{first: $current, extract: "\(.first)"}
elif has("last") and .last + 1 != $current then
{first: $current, extract: "\(.first)-\(.last)"}
else
{first, last: $current}
end;
.extract // empty
)]
| join(",")
我会分两步完成。
首先,分组到范围内。
reduce .[] as $_ (
[];
if $_ - 1 == .[-1][1] then
.[-1][1] = $_
else
. + [ [ $_, $_ ] ]
end
)
此步骤生成 [[1,1],[2,4],[6,6],[98,99],[101,101]]
。
然后,构建字符串。
map(
if .[0] == .[1] then
"\( .[0] )"
else
"\( .[0] )-\( .[1] )"
end
) |
join(",")
Demo 在 jqplay
它并没有短多少,但我认为它更简单、更清晰。
此外,分离关注点不仅对简单性和清晰性有好处。您可以选择将代码隐藏在两个小函数中。您可以更轻松地自定义输出,比如为 [98,99]
生成 98,99
而不是 98-99
。您甚至可以决定重用根本不需要生成字符串的代码。
但最重要的是,此解决方案消除了魔法 99999
!
这是另一个解决方案:
reduce .[1:][] as $n ([.[:1]];
if $n == .[-1][-1] + 1 then .[-1][1] = $n else . + [[$n]] end
) | map(join("-")) | join(",")
喂食时
[1,2,3,4,6,98,99,101]
[1,3,5]
[1,2,3,4,5]
[4]
[]
它输出
"1-4,6,98-99,101"
"1,3,5"
"1-5"
"4"
""