2017-09-30 8 views
-2

私はperlでsybaseテーブルの行数を取得しています。たとえば、テーブルに100行あり、n = 100perlで3つの方法でテーブルの行数を分割

この値を3つに分割したい 1-33 | 34-66 | 67-99または100

これをperlでどうやって得るのかアドバイスしてください。この分割の

理由:私は、その同一列の値である同じ

1〜33 34から66 & 67についても行を選択するストアドプロシージャへの入力パラメータとして値1と33を通過する必要があります-99

答えて

0

興味深いのは、各範囲の開始位置を決定することです。そこから、各範囲が次の範囲の開始点よりも1つ小さいと判断するのは簡単です。

このpartition()関数は、与えられたオフセットで開始する指定された数の要素内の与えられた数のパーティションの開始点を決定します。ここで

sub partition { 
    my ($offset, $n_elements, $n_partitions) = @_; 

    die "Cannot create $n_partitions partitions from $n_elements elements.\n" 
     if $n_partitions > $n_elements; 

    my $step = int($n_elements/$n_partitions); 

    return map {$step * $_ + $offset} 0 .. $n_partitions - 1; 
} 

は、それがどのように動作するかです:

まず、ステップは、パーティションの数によって要素の数を分割し、末尾の小数点以下を切り捨てて整数を保存することでどうあるべきかを決定します。

次に、ゼロから開始し、ステップ番号(またはパーティション番号)を掛けてステップを実行します。したがって、ステップが5の場合、5 * 0 = 0,5x1 = 5,5x2 = 10などとなります。最後のステップでは、1つの要素だけで新しいパーティションを開始するよりも、最後のパーティションに「オフ・バイ・ワン」を含めるほうが意味があるため、最後のステップは見ません。

最後に、オフセットを適用できるようにします。partition(0,100,5)は、ゼロから開始し100個の要素(0〜99の範囲)まで続く5つのパーティションの開始要素位置を見つけることを意味します。そしてpartition(1,100,5)は、1から始まり、5つのセグメントで100個の要素の分割を続けることを意味するので、1から100の範囲になります。

ここでは、いくつかの範囲のセットでパーティションポイントを見つけるために関数を使用します。

use strict; 
use warnings; 
use Test::More; 

sub partition { 
    my ($offset, $n_elements, $n_partitions) = @_; 

    die "Cannot create $n_partitions partitions from $n_elements elements.\n" 
     if $n_partitions > $n_elements; 

    my $step = int($n_elements/$n_partitions); 

    return map {$step * $_ + $offset} 0 .. $n_partitions - 1; 
} 

while(<DATA>) { 
    chomp; 
    next unless length; 

    my ($off, $n_elems, $n_parts, @starts) = split /,\s*/; 

    local $" = ','; 

    is_deeply 
     [partition($off, $n_elems, $n_parts)], 
     [@starts], 
     "Partitioning $n_elems elements starting at $off by $n_parts yields start positions of [@starts]"; 
} 

done_testing(); 

__DATA__ 
0,10,2,0,5 
1,11,2,1,6 
0,3,2,0,1 
0,7,3,0,2,4 
0,21,3,0,7,14 
0,21,7,0,3,6,9,12,15,18 
0,20,3,0,6,12 
0,100,4,0,25,50,75 
1,100,4,1,26,51,76 
1,100,3,1,34,67 
0,10,1,0 
1,10,10,1,2,3,4,5,6,7,8,9,10 

これは、次のような出力が得られます。追加の例については

ok 1 - Partitioning 10 elements starting at 0 by 2 yields start positions of [0,5] 
ok 2 - Partitioning 11 elements starting at 1 by 2 yields start positions of [1,6] 
ok 3 - Partitioning 3 elements starting at 0 by 2 yields start positions of [0,1] 
ok 4 - Partitioning 7 elements starting at 0 by 3 yields start positions of [0,2,4] 
ok 5 - Partitioning 21 elements starting at 0 by 3 yields start positions of [0,7,14] 
ok 6 - Partitioning 21 elements starting at 0 by 7 yields start positions of [0,3,6,9,12,15,18] 
ok 7 - Partitioning 20 elements starting at 0 by 3 yields start positions of [0,6,12] 
ok 8 - Partitioning 100 elements starting at 0 by 4 yields start positions of [0,25,50,75] 
ok 9 - Partitioning 100 elements starting at 1 by 4 yields start positions of [1,26,51,76] 
ok 10 - Partitioning 100 elements starting at 1 by 3 yields start positions of [1,34,67] 
ok 11 - Partitioning 10 elements starting at 0 by 1 yields start positions of [0] 
ok 12 - Partitioning 10 elements starting at 1 by 10 yields start positions of [1,2,3,4,5,6,7,8,9,10] 
1..12 

はPerlMonksにSplit range 0 to M into N non-overlapping (roughly equal) ranges.を見てください。

あなたの質問は完全な範囲の開始点と終了点を探しています。この方法では、それはむしろ些細ます:

sub partition { 
    my ($offset, $n_elements, $n_partitions) = @_; 
    my $step = int($n_elements/$n_partitions); 
    return map {$step * $_ + $offset} 0 .. $n_partitions - 1; 
} 

my $n_elems = 100; 
my $offset = 1; 
my $n_parts = 3; 

my @starts = partition($offset, $n_elems, $n_parts); 

my @ranges = map{ 
    [ 
     $starts[$_], 
     ($starts[$_+1] // $n_elems+$offset)-1, 
    ] 
} 0..$#starts; 

print "($_->[0], $_->[1])\n" foreach @ranges; 

出力:

(1, 33) 
(34, 66) 
(67, 100) 

さらに実装例がStackExchangeソフトウェア工学フォーラムにAlgorithm for dividing a range into ranges and then finding which range a number belongs toに表示されます。

関連する問題