How to collapse consecutive numbers into ranges?
Clash Royale CLAN TAG#URR8PPP
up vote
4
down vote
favorite
Given a sorted input file (or command output) that contains unique numbers, one per line, I would like to collapse all runs of consecutive numbers into ranges such that
n
n+1
...
n+m
becomes
n,n+m
input sample:
2
3
9
10
11
12
24
28
29
33
expected output:
2,3
9,12
24
28,29
33
text-processing numeric-data
add a comment |Â
up vote
4
down vote
favorite
Given a sorted input file (or command output) that contains unique numbers, one per line, I would like to collapse all runs of consecutive numbers into ranges such that
n
n+1
...
n+m
becomes
n,n+m
input sample:
2
3
9
10
11
12
24
28
29
33
expected output:
2,3
9,12
24
28,29
33
text-processing numeric-data
Very nice question, but would benefit from some clarifications for newbies. Please !
â TNT
7 hours ago
@TNT - let me know which part is unclear
â don_crissti
6 hours ago
thank you. just not clear to me what it means n then n+1. given first number is 2 then I assume first range 2,3 then second range should be 9,10 then 10-11 how you calculated the "expected output" ranges. Would be appreciated if you explain.
â TNT
5 hours ago
@TNT - consecutive ="following each other continuously" (I'm 100% sure consecutive has the same meaning in all languages) so when I say collapse all consecutive numbers I mean all consecutive numbers liken
,n+1
,n+2
,n+3
and so on (Ã lan++
) up ton+m
should be combined into a single range:n,n+m
. So combine as many numbers as possible as long as they are consecutive.
â don_crissti
4 hours ago
add a comment |Â
up vote
4
down vote
favorite
up vote
4
down vote
favorite
Given a sorted input file (or command output) that contains unique numbers, one per line, I would like to collapse all runs of consecutive numbers into ranges such that
n
n+1
...
n+m
becomes
n,n+m
input sample:
2
3
9
10
11
12
24
28
29
33
expected output:
2,3
9,12
24
28,29
33
text-processing numeric-data
Given a sorted input file (or command output) that contains unique numbers, one per line, I would like to collapse all runs of consecutive numbers into ranges such that
n
n+1
...
n+m
becomes
n,n+m
input sample:
2
3
9
10
11
12
24
28
29
33
expected output:
2,3
9,12
24
28,29
33
text-processing numeric-data
text-processing numeric-data
edited 7 hours ago
Jeff Schaller
32.6k849110
32.6k849110
asked 7 hours ago
don_crissti
47.2k15125155
47.2k15125155
Very nice question, but would benefit from some clarifications for newbies. Please !
â TNT
7 hours ago
@TNT - let me know which part is unclear
â don_crissti
6 hours ago
thank you. just not clear to me what it means n then n+1. given first number is 2 then I assume first range 2,3 then second range should be 9,10 then 10-11 how you calculated the "expected output" ranges. Would be appreciated if you explain.
â TNT
5 hours ago
@TNT - consecutive ="following each other continuously" (I'm 100% sure consecutive has the same meaning in all languages) so when I say collapse all consecutive numbers I mean all consecutive numbers liken
,n+1
,n+2
,n+3
and so on (Ã lan++
) up ton+m
should be combined into a single range:n,n+m
. So combine as many numbers as possible as long as they are consecutive.
â don_crissti
4 hours ago
add a comment |Â
Very nice question, but would benefit from some clarifications for newbies. Please !
â TNT
7 hours ago
@TNT - let me know which part is unclear
â don_crissti
6 hours ago
thank you. just not clear to me what it means n then n+1. given first number is 2 then I assume first range 2,3 then second range should be 9,10 then 10-11 how you calculated the "expected output" ranges. Would be appreciated if you explain.
â TNT
5 hours ago
@TNT - consecutive ="following each other continuously" (I'm 100% sure consecutive has the same meaning in all languages) so when I say collapse all consecutive numbers I mean all consecutive numbers liken
,n+1
,n+2
,n+3
and so on (Ã lan++
) up ton+m
should be combined into a single range:n,n+m
. So combine as many numbers as possible as long as they are consecutive.
â don_crissti
4 hours ago
Very nice question, but would benefit from some clarifications for newbies. Please !
â TNT
7 hours ago
Very nice question, but would benefit from some clarifications for newbies. Please !
â TNT
7 hours ago
@TNT - let me know which part is unclear
â don_crissti
6 hours ago
@TNT - let me know which part is unclear
â don_crissti
6 hours ago
thank you. just not clear to me what it means n then n+1. given first number is 2 then I assume first range 2,3 then second range should be 9,10 then 10-11 how you calculated the "expected output" ranges. Would be appreciated if you explain.
â TNT
5 hours ago
thank you. just not clear to me what it means n then n+1. given first number is 2 then I assume first range 2,3 then second range should be 9,10 then 10-11 how you calculated the "expected output" ranges. Would be appreciated if you explain.
â TNT
5 hours ago
@TNT - consecutive ="following each other continuously" (I'm 100% sure consecutive has the same meaning in all languages) so when I say collapse all consecutive numbers I mean all consecutive numbers like
n
, n+1
, n+2
, n+3
and so on (Ã la n++
) up to n+m
should be combined into a single range: n,n+m
. So combine as many numbers as possible as long as they are consecutive.â don_crissti
4 hours ago
@TNT - consecutive ="following each other continuously" (I'm 100% sure consecutive has the same meaning in all languages) so when I say collapse all consecutive numbers I mean all consecutive numbers like
n
, n+1
, n+2
, n+3
and so on (Ã la n++
) up to n+m
should be combined into a single range: n,n+m
. So combine as many numbers as possible as long as they are consecutive.â don_crissti
4 hours ago
add a comment |Â
4 Answers
4
active
oldest
votes
up vote
4
down vote
awk '
function output() print start (prev == start ? "" : ","prev)
NR == 1 start = prev = $1; next
$1 > prev+1 output(); start = $1
prev = $1
END output()
'
add a comment |Â
up vote
2
down vote
Perl
approach!
#!/bin/perl
print ranges(2,3,9,10,11,12,24,28,29,33), "n";
sub ranges
my @vals = @_;
my $first = $vals[0];
my $last;
my @list;
for my $i (0 .. (scalar(@vals)-2))
if (($vals[$i+1] - $vals[$i]) != 1)
$last = $vals[$i];
push @list, ($first == $last) ? $first : "$first,$last";
$first = $vals[$i+1];
$last = $vals[-1];
push @list, ($first == $last) ? $first : "$first,$last";
return join ("n", @list);
2
24,24
and33,33
is not quite what was requested...
â RudiC
6 hours ago
As your awk approach is quite similar to glenn jackman's and mine, refer to those.
â RudiC
4 hours ago
add a comment |Â
up vote
1
down vote
How about
awk '
$0 > LAST+1 if (NR > 1) print (PR != LAST)?"," LAST:""
printf "%s", $0
PR = $0
LAST = $0
END print (PR != LAST)?"," LAST:""
' file
2,3
9,12
24
28,29
33
I'd stick to lower case variable names, but that's just style. I came up with the same logic.
â glenn jackman
7 hours ago
Actually, there is a bug here: if the first line is less than one, the first condition will be false, so the the first number will not be printed. You need a separate rule forNR==1
â glenn jackman
7 hours ago
I might recheck. I'm not too happy with the clumsy logics anyhow.
â RudiC
7 hours ago
add a comment |Â
up vote
1
down vote
awk
, with a different (more C
-like) approach:
awk ' do for(s=e=$1; (r=getline)>0 && $1<=e+1; e=$1); print s==e ? s : s","e while(r>0) ' file
add a comment |Â
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
4
down vote
awk '
function output() print start (prev == start ? "" : ","prev)
NR == 1 start = prev = $1; next
$1 > prev+1 output(); start = $1
prev = $1
END output()
'
add a comment |Â
up vote
4
down vote
awk '
function output() print start (prev == start ? "" : ","prev)
NR == 1 start = prev = $1; next
$1 > prev+1 output(); start = $1
prev = $1
END output()
'
add a comment |Â
up vote
4
down vote
up vote
4
down vote
awk '
function output() print start (prev == start ? "" : ","prev)
NR == 1 start = prev = $1; next
$1 > prev+1 output(); start = $1
prev = $1
END output()
'
awk '
function output() print start (prev == start ? "" : ","prev)
NR == 1 start = prev = $1; next
$1 > prev+1 output(); start = $1
prev = $1
END output()
'
answered 7 hours ago
glenn jackman
47.6k265104
47.6k265104
add a comment |Â
add a comment |Â
up vote
2
down vote
Perl
approach!
#!/bin/perl
print ranges(2,3,9,10,11,12,24,28,29,33), "n";
sub ranges
my @vals = @_;
my $first = $vals[0];
my $last;
my @list;
for my $i (0 .. (scalar(@vals)-2))
if (($vals[$i+1] - $vals[$i]) != 1)
$last = $vals[$i];
push @list, ($first == $last) ? $first : "$first,$last";
$first = $vals[$i+1];
$last = $vals[-1];
push @list, ($first == $last) ? $first : "$first,$last";
return join ("n", @list);
2
24,24
and33,33
is not quite what was requested...
â RudiC
6 hours ago
As your awk approach is quite similar to glenn jackman's and mine, refer to those.
â RudiC
4 hours ago
add a comment |Â
up vote
2
down vote
Perl
approach!
#!/bin/perl
print ranges(2,3,9,10,11,12,24,28,29,33), "n";
sub ranges
my @vals = @_;
my $first = $vals[0];
my $last;
my @list;
for my $i (0 .. (scalar(@vals)-2))
if (($vals[$i+1] - $vals[$i]) != 1)
$last = $vals[$i];
push @list, ($first == $last) ? $first : "$first,$last";
$first = $vals[$i+1];
$last = $vals[-1];
push @list, ($first == $last) ? $first : "$first,$last";
return join ("n", @list);
2
24,24
and33,33
is not quite what was requested...
â RudiC
6 hours ago
As your awk approach is quite similar to glenn jackman's and mine, refer to those.
â RudiC
4 hours ago
add a comment |Â
up vote
2
down vote
up vote
2
down vote
Perl
approach!
#!/bin/perl
print ranges(2,3,9,10,11,12,24,28,29,33), "n";
sub ranges
my @vals = @_;
my $first = $vals[0];
my $last;
my @list;
for my $i (0 .. (scalar(@vals)-2))
if (($vals[$i+1] - $vals[$i]) != 1)
$last = $vals[$i];
push @list, ($first == $last) ? $first : "$first,$last";
$first = $vals[$i+1];
$last = $vals[-1];
push @list, ($first == $last) ? $first : "$first,$last";
return join ("n", @list);
Perl
approach!
#!/bin/perl
print ranges(2,3,9,10,11,12,24,28,29,33), "n";
sub ranges
my @vals = @_;
my $first = $vals[0];
my $last;
my @list;
for my $i (0 .. (scalar(@vals)-2))
if (($vals[$i+1] - $vals[$i]) != 1)
$last = $vals[$i];
push @list, ($first == $last) ? $first : "$first,$last";
$first = $vals[$i+1];
$last = $vals[-1];
push @list, ($first == $last) ? $first : "$first,$last";
return join ("n", @list);
edited 4 hours ago
answered 7 hours ago
Goro
3,05441951
3,05441951
2
24,24
and33,33
is not quite what was requested...
â RudiC
6 hours ago
As your awk approach is quite similar to glenn jackman's and mine, refer to those.
â RudiC
4 hours ago
add a comment |Â
2
24,24
and33,33
is not quite what was requested...
â RudiC
6 hours ago
As your awk approach is quite similar to glenn jackman's and mine, refer to those.
â RudiC
4 hours ago
2
2
24,24
and 33,33
is not quite what was requested...â RudiC
6 hours ago
24,24
and 33,33
is not quite what was requested...â RudiC
6 hours ago
As your awk approach is quite similar to glenn jackman's and mine, refer to those.
â RudiC
4 hours ago
As your awk approach is quite similar to glenn jackman's and mine, refer to those.
â RudiC
4 hours ago
add a comment |Â
up vote
1
down vote
How about
awk '
$0 > LAST+1 if (NR > 1) print (PR != LAST)?"," LAST:""
printf "%s", $0
PR = $0
LAST = $0
END print (PR != LAST)?"," LAST:""
' file
2,3
9,12
24
28,29
33
I'd stick to lower case variable names, but that's just style. I came up with the same logic.
â glenn jackman
7 hours ago
Actually, there is a bug here: if the first line is less than one, the first condition will be false, so the the first number will not be printed. You need a separate rule forNR==1
â glenn jackman
7 hours ago
I might recheck. I'm not too happy with the clumsy logics anyhow.
â RudiC
7 hours ago
add a comment |Â
up vote
1
down vote
How about
awk '
$0 > LAST+1 if (NR > 1) print (PR != LAST)?"," LAST:""
printf "%s", $0
PR = $0
LAST = $0
END print (PR != LAST)?"," LAST:""
' file
2,3
9,12
24
28,29
33
I'd stick to lower case variable names, but that's just style. I came up with the same logic.
â glenn jackman
7 hours ago
Actually, there is a bug here: if the first line is less than one, the first condition will be false, so the the first number will not be printed. You need a separate rule forNR==1
â glenn jackman
7 hours ago
I might recheck. I'm not too happy with the clumsy logics anyhow.
â RudiC
7 hours ago
add a comment |Â
up vote
1
down vote
up vote
1
down vote
How about
awk '
$0 > LAST+1 if (NR > 1) print (PR != LAST)?"," LAST:""
printf "%s", $0
PR = $0
LAST = $0
END print (PR != LAST)?"," LAST:""
' file
2,3
9,12
24
28,29
33
How about
awk '
$0 > LAST+1 if (NR > 1) print (PR != LAST)?"," LAST:""
printf "%s", $0
PR = $0
LAST = $0
END print (PR != LAST)?"," LAST:""
' file
2,3
9,12
24
28,29
33
edited 7 hours ago
answered 7 hours ago
RudiC
1,2167
1,2167
I'd stick to lower case variable names, but that's just style. I came up with the same logic.
â glenn jackman
7 hours ago
Actually, there is a bug here: if the first line is less than one, the first condition will be false, so the the first number will not be printed. You need a separate rule forNR==1
â glenn jackman
7 hours ago
I might recheck. I'm not too happy with the clumsy logics anyhow.
â RudiC
7 hours ago
add a comment |Â
I'd stick to lower case variable names, but that's just style. I came up with the same logic.
â glenn jackman
7 hours ago
Actually, there is a bug here: if the first line is less than one, the first condition will be false, so the the first number will not be printed. You need a separate rule forNR==1
â glenn jackman
7 hours ago
I might recheck. I'm not too happy with the clumsy logics anyhow.
â RudiC
7 hours ago
I'd stick to lower case variable names, but that's just style. I came up with the same logic.
â glenn jackman
7 hours ago
I'd stick to lower case variable names, but that's just style. I came up with the same logic.
â glenn jackman
7 hours ago
Actually, there is a bug here: if the first line is less than one, the first condition will be false, so the the first number will not be printed. You need a separate rule for
NR==1
â glenn jackman
7 hours ago
Actually, there is a bug here: if the first line is less than one, the first condition will be false, so the the first number will not be printed. You need a separate rule for
NR==1
â glenn jackman
7 hours ago
I might recheck. I'm not too happy with the clumsy logics anyhow.
â RudiC
7 hours ago
I might recheck. I'm not too happy with the clumsy logics anyhow.
â RudiC
7 hours ago
add a comment |Â
up vote
1
down vote
awk
, with a different (more C
-like) approach:
awk ' do for(s=e=$1; (r=getline)>0 && $1<=e+1; e=$1); print s==e ? s : s","e while(r>0) ' file
add a comment |Â
up vote
1
down vote
awk
, with a different (more C
-like) approach:
awk ' do for(s=e=$1; (r=getline)>0 && $1<=e+1; e=$1); print s==e ? s : s","e while(r>0) ' file
add a comment |Â
up vote
1
down vote
up vote
1
down vote
awk
, with a different (more C
-like) approach:
awk ' do for(s=e=$1; (r=getline)>0 && $1<=e+1; e=$1); print s==e ? s : s","e while(r>0) ' file
awk
, with a different (more C
-like) approach:
awk ' do for(s=e=$1; (r=getline)>0 && $1<=e+1; e=$1); print s==e ? s : s","e while(r>0) ' file
edited 6 hours ago
don_crissti
47.2k15125155
47.2k15125155
answered 6 hours ago
mosvy
7176
7176
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f470073%2fhow-to-collapse-consecutive-numbers-into-ranges%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Very nice question, but would benefit from some clarifications for newbies. Please !
â TNT
7 hours ago
@TNT - let me know which part is unclear
â don_crissti
6 hours ago
thank you. just not clear to me what it means n then n+1. given first number is 2 then I assume first range 2,3 then second range should be 9,10 then 10-11 how you calculated the "expected output" ranges. Would be appreciated if you explain.
â TNT
5 hours ago
@TNT - consecutive ="following each other continuously" (I'm 100% sure consecutive has the same meaning in all languages) so when I say collapse all consecutive numbers I mean all consecutive numbers like
n
,n+1
,n+2
,n+3
and so on (Ã lan++
) up ton+m
should be combined into a single range:n,n+m
. So combine as many numbers as possible as long as they are consecutive.â don_crissti
4 hours ago