我现在有一个整数数组,如, (1,13,3,5,6,7,11,10,8,2,12) 我想让连续的子区域形成这个数组, 上述数组的结果应为(1,3),(5,8),(10,13)
阵列可能非常大。有人有什么想法吗?
非常感谢。
答案 0 :(得分:5)
您可以使用Set::IntSpan
模块:
use strict;
use warnings;
use Data::Dump;
use Set::IntSpan;
my @values = (1, 13, 3, 5, 6, 7, 11, 10, 8, 2, 12);
my $set = Set::IntSpan->new(@values);
my @spans = $set->spans;
dd @spans;
([1, 3], [5, 8], [10, 13])
如果一个运行只包含一个数字,则下限和上限将相同,例如[42, 42]
。
正如salva在评论中指出的那样,Set::IntSpan
在大量范围内表现不佳。另一种选择是Set::IntSpan::Fast
,根据documentation,它使用二进制搜索并趋向于O log N性能。如果您同时安装Set::IntSpan::Fast::XS
,您将获得更好的性能(无需更改use
声明,如果已安装XS版本,则会自动使用。)
以下内容遍历范围并将它们推送到数组:
use strict;
use warnings;
use Data::Dump;
use Set::IntSpan::Fast;
my @values = (1, 13, 3, 5, 6, 7, 11, 10, 8, 2, 12);
my $set = Set::IntSpan::Fast->new;
$set->add(@values);
my @ranges;
my $iter = $set->iterate_runs;
while (my ($from, $to) = $iter->()) {
push @ranges, [ $from, $to ];
}
dd @ranges;
([1, 3], [5, 8], [10, 13])
请注意,要对范围执行任何有用的操作,您必须遍历此数组;在第一次迭代集合而不是遍历两个不同的结构时,完成工作会更有效。
答案 1 :(得分:3)
使用散列,获取一些随机元素并查找前后的连续元素:
my @ints = (...);
my %ints = map { $_ => 1 } @ints;
my @ranges;
while (keys %ints) {
my $bottom = my $top = each %ints;
delete $ints{$bottom};
1 while (delete $ints{--$bottom});
1 while (delete $ints{++$top});
push @ranges, [$bottom + 1, $top - 1];
}
say join ', ', map "$_->[0]-$_->[1]", @ranges;
答案 2 :(得分:1)
如果您想以最小的努力快速完成工作,请在Set::IntSpan
中使用ThisSuitIsBlackNot作为answer建议。
如果您想要DIY工作,那么您可以考虑使用此代码作为基础:
#!/usr/bin/env perl
use strict;
use warnings;
$, = " ";
my @data = (1, 13, 3, 5, 6, 7, 11, 10, 8, 2, 12);
sub pr_region
{
my($lo, $hi) = @_;
print "($lo";
print ", $hi" if ($lo != $hi);
print ")\n";
}
sub print_regions
{
my(@data) = @_;
print "Raw: ", @data, "\n";
my @sorted = sort { $a <=> $b } @data;
#print "Sorted: ", @sorted, "\n";
my $lo = $sorted[0];
for my $i (1 .. scalar(@sorted)-1)
{
if ($sorted[$i-1] != $sorted[$i] - 1 &&
$sorted[$i-1] != $sorted[$i])
{
pr_region($lo, $sorted[$i-1]);
$lo = $sorted[$i];
}
}
pr_region($lo, $sorted[$#sorted]);
}
print_regions(@data);
print_regions(1);
print_regions(1, 10);
print_regions(1, 2, 10);
print_regions(1, 9, 10);
print_regions(@data, 11, 3, 19, -3);
它的输出是:
Raw: 1 13 3 5 6 7 11 10 8 2 12
(1, 3)
(5, 8)
(10, 13)
Raw: 1
(1)
Raw: 1 10
(1)
(10)
Raw: 1 2 10
(1, 2)
(10)
Raw: 1 9 10
(1)
(9, 10)
Raw: 1 13 3 5 6 7 11 10 8 2 12 11 3 19 -3
(-3)
(1, 3)
(5, 8)
(10, 13)
(19)
我没有尽力减少代码。它打印结果而不是将它们打包在数据结构中以便重复使用。它没有处理空数组。