首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在perl数组中对序列号进行分组?

如何在perl数组中对序列号进行分组?
EN

Stack Overflow用户
提问于 2015-08-04 07:16:02
回答 2查看 765关注 0票数 3

我正在尝试编写一个perl脚本,如果我有一个示例数组,如下所示:

代码语言:javascript
复制
@array = (0,1,2,3,4,8,9,10,12,14,16,17,19)

然后我需要转换/格式化这个数组,这样我就可以得到如下格式的输出:

代码语言:javascript
复制
output_bus[0-4, 8-10, 12, 14, 16-17, 19]
EN

回答 2

Stack Overflow用户

发布于 2015-08-04 07:26:09

代码语言:javascript
复制
use Number::Range;
my $range = Number::Range->new();
$range->addrange(0,1,2,3,4,8,9,10,12,14,16,17,19);
my $range_list = join ', ', map join('-',@$_), $range->rangeList;

(rangeList返回,例如[0,4],[8,10],[12],[14],[16,17],[19])

还有Set::IntSpan,它或多或少做同样的事情,只是使用重载、无限范围和其他额外的东西。它做这件事的方式有点麻烦:

代码语言:javascript
复制
use Set::IntSpan 'grep_spans';

my @array = (0, 1, 2, 3, 4, 8, 9, 10, 12, 14, 16, 17, 19);

my $set = Set::IntSpan->new(@array);
my @range_list;
grep_spans {
    push @range_list, $_->[0] == $_->[1] ? $_->[0] : "$_->[0]-$_->[1]";
} $set;
my $range_list = join ', ', @range_list;

这里有另一种方法:

代码语言:javascript
复制
my $range_list = List::Util::reduce { $a =~ /^\z/ ? "$b" : $a =~ /-(@{[$b-1]})\z/ ? ($a =~ s/$1\z/$b/, $a) : $a =~ /(?<![0-9])@{[$b-1]}\z/ ? "$a-$b" : "$a, $b" } '', 0,1,2,3,4,8,9,10,12,14,16,17,19;
票数 7
EN

Stack Overflow用户

发布于 2015-08-04 07:59:13

巧合的是,我写了一个子例程来做这件事,作为我对this question的回答的一部分。这里,它再次使用您自己的数据作为输入。代码假定传递的参数是按数字顺序排序的

代码语言:javascript
复制
use strict;
use warnings;

my @array = (0, 1, 2, 3, 4, 8, 9, 10, 12, 14, 16, 17, 19);

printf "output_bus[%s]\n", ranges( @array );

sub ranges {

    my @ranges;
    my ($start, $end);

    for my $n ( @_ ) {
        if ( not defined $start ) {
            $start = $end = $n;
        }
        elsif ( $n == $end + 1 ) {
            $end = $n;
        }
        else {
            push @ranges, $start == $end ? $start : "$start-$end";
            $start = $end = $n;
        }
    }

    push @ranges, $start == $end ? $start : "$start-$end" if defined $start;
    join ', ', @ranges;
}

输出

代码语言:javascript
复制
output_bus[0-4, 8-10, 12, 14, 16-17, 19]

或者,正如DavidO在他对该问题的解决方案中所建议的那样,Set::IntSpan模块可以为您完成此任务,而无需考虑

下面是使用该模块的解决方案。唯一的区别是逗号后面没有空格,但这可以非常简单地解决

代码语言:javascript
复制
use strict;
use warnings;

use Set::IntSpan;

my @array = (0, 1, 2, 3, 4, 8, 9, 10, 12, 14, 16, 17, 19);

printf "output_bus[%s]\n", Set::IntSpan->new(@array);

输出

代码语言:javascript
复制
output_bus[0-4,8-10,12,14,16-17,19]

如果有人来到这里,希望了解如何遍历Set::IntSpan对象,下面的代码可以很好地工作。文档讨论了startfirstnextcurrentprevlast方法,但没有很好地描述它们。start是一个重置,而next将传递集合的下一个元素,直到它返回undef时到达末尾

这个C风格的for循环遍历所有集合

代码语言:javascript
复制
for ( my $n = $set->first; defined $n; $n = $set->next ) {
    say $n;
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31798224

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档