Это похоже на то, что вы хотите.
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
while (<DATA>) {
chomp;
say rangify(split /,/);
}
sub rangify {
my @nums = @_;
my @range;
for (0 .. $#nums) {
if ($_ == 0 or $nums[$_] != $nums[$_ - 1] + 1) {
push @range, [ $nums[$_] ];
} else {
push @{$range[-1]}, $nums[$_];
}
}
for (@range) {
if (@$_ == 1) {
$_ = $_->[0];
} else {
$_ = "$_->[0]-$_->[-1]";
}
}
return join ',', @range;
}
__DATA__
1,2,5
1,2,3,5,7
100,101,102,103,115,120,121
Функция rangify()
создает массив массивов. Он пересекает ваш входной список и, если число на единицу больше предыдущего, то добавляет новый номер в массив второго уровня, который в данный момент находится в конце массива первого уровня. Если новое число не является последовательным, оно добавляет новый массив второго уровня в конец массива первого уровня.
Построив эту структуру данных, мы проходим массив первого уровня, просматривая каждый измассивы второго уровня. Если массив второго уровня содержит только один элемент, мы знаем, что это не диапазон, поэтому мы перезаписываем значение одним числом из массива. Если он содержит более одного элемента, то это диапазон, и мы перезаписываем значение первым и последним элементами, разделенными дефисом.