2016-10-12 5 views
1

私はいくつかのペアのペアを持ち、最初のものが所定のインターバルに入るかどうかをチェックします。もしそうなら、私はペアの第2の数が第1の数よりも多いか少ないかに応じて、その間隔の2つのカウンターの1つを増分したいと思います。perl:ハッシュキーで番号にインターバルを割り当て、番号がインターバル内にある場合はインクリメントカウンタを設定します。

間隔は単純で、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 

のように見える私の考えでは、キーとの間隔の開始とのハッシュを作成し、値に二つのカウンタを保存することでした。

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

しかし、今では数字をキーと比較する方法とカウンターに対処する方法がわかりません。 ありがとうございました!

+1

期待していることは完全にはっきりしていません。いくつかの入力と期待される出力を提供できますか? – xxfelixxx

+0

ok私は何千もの間隔とさらに多くの数の対を持っていることを忘れています。だから私はループのネストで各ペアと間隔を避けたかった:( – Jule

+0

また、入力の形式はそれほど重要ではない – Jule

答えて

0

カウンタを各間隔で保持する場合は、選択したデータ構造にカウンタを記録できます。たとえば、インターバルインデックスをキーとし、ハーフハイトカウンタを2要素の再配列の値としてハッシュ内の各インターバルにカウンタを格納します。

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を持つ)自体である可能性があります。もう1つの可能性は、2要素配列の代わりに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; 
+0

OPはおそらく統計的なテストのためにデータを前処理しているだろう –

+0

OPの望ましい出力から、 OPはすべての区間で別々に記録されることを望んでいます汚い方法は、 '$ inter - > [2]'を高く、3つを低くすることです - より良い方法は '@ records'を定義し、' $ –

+0

@SunnyPunコメントをいただきありがとうございます - はい、そのように見えましたが、わかりませんでした。答えに追加されました – zdim

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; 
関連する問題