perl:使用散列键将间隔分配给数字,如果数字在间隔

时间:2016-10-12 16:29:07

标签: perl hash compare key

我有几对数字,想要检查第一个是否属于给定的间隔。如果是这样,我想为该间隔增加两个计数器中的一个,具体取决于该对的第二个数字是高于还是低于第一个。

间隔很简单,看起来像1-10,11-20,21-30等。数字对看起来像(5,15),(24,13)等。但我有几千个。确切的输入格式并不重要。

期望的结果如下所示

1-10: higher=1, lower=0
11-20: higher=0,lower=0
21-30: higher=0,lower=1

我的想法是创建一个以间隔start作为键的哈希值,并将两个计数器存储在值中。

for(my $i = $start;$i<=$end;$i = ($i+$intervalsize)){
    my $counter1 = 0;
    my $counter2 = 0;
    @{$hash{$i}} = ($counter1,$counter2);

但现在我不知道如何比较数字和键以及如何处理计数器。 谢谢你的帮助!

2 个答案:

答案 0 :(得分:0)

如果要为每个间隔保留计数器,我们可以将它们记录在所选的数据结构中。例如,在散列中为每个时间间隔存储计数器,其中键是间隔索引,而低 - 高计数器在两元素的重组中作为其值。

use warnings 'all';
use strict;

my @intervals = ( [1,10], [11,20], [21,30] );
my @pairs     = ( [5,15], [24, 13] );

my %counter = map { $_ => [0,0] } (0..$#intervals);  # initialize

foreach my $i (0..$#intervals) 
{
    foreach my $pair (@pairs)
    {   
        my ($beg, $end) = @{$intervals[$i]};
        my ($pl, $pr)   = @$pair;

        if ($pl >= $beg and $pl <= $end) 
        {   
            if ($pr > $pl) { ++$counter{$i}[1] }   
            else           { ++$counter{$i}[0] }   
        }   
    }   
}

print "$_ => @{$counter{$_}}\n" for sort keys %counter;

这仍然是基本的,以便更容易调整。首先,由于哈希使用@intervals数组的索引,因此它本身可能是一个数组(带有arrayrefs)。另一种可能性是使用带有lowhigh等键的哈希值作为计数器而不是双元素数组。

为了使用间隔开始作为关键

my %counter = map { $_->[0] => [0,0] } @intervals;  # initialize

for my $inter (@intervals) {
    for my $pair (@pairs) {
        my ($beg, $end) = @$inter;
        my ($pl, $pr)   = @$pair;

        if ($pl >= $beg and $pr <= $end) 
        {   
            if ($pr > $pl) { ++$counter{$beg}[1] }
            else           { ++$counter{$end}[0] }
        }
    }
}
printf("%3d => @{$counter{$_}}\n", $_) for sort keys %counter;

答案 1 :(得分:0)

这样的事可能吗?

#!/usr/bin/env perl

use strict;
use warnings;

use List::MoreUtils qw( first_index );

sub interval_to_key { sprintf '(%d,%d)', @{ $_[0] } }

my @intervals = (
    [  1, 10 ],
    [ 11, 20 ],
    [ 21, 30 ],
);

my @upper_bounds = map $_->[0], @intervals;

my @pairs = (
    [  5, 15 ],
    [ 24, 13 ],
);

my @keys = qw( ascending descending );

my %counts;

for my $interval ( @intervals ) {
    @{ $counts{ interval_to_key($interval) } }{ @keys } = (0) x @keys;
}

for my $pair ( @pairs ) {
    my $is_ascending = ($pair->[0] <= $pair->[1]);

    my $i = first_index { $pair->[0] <= $_ } @upper_bounds;

    ++ $counts{ interval_to_key( $intervals[$i]) }{ $keys[1 - $is_ascending] };
}

use Data::Dumper;
print Dumper \%counts;