Perl楽しいから好き

Perlをはじめとしたプログラミング周りのあれこれについて。モダーンなPerlを楽しんでいます。

Perlで、とある配列を指定した要素数ごとに別の配列リファレンスに分割する処理

my @arr = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);

↑ こういう感じの配列を、

my $expected = [
    [ 1, 2, 3, 4 ],
    [ 5, 6, 7, 8 ],
    [ 9, 10, 11, 12 ]
];

↑ こういう感じに分割したい欲望に駆られました。この場合は、13個の要素を持つ配列を4つの要素ずつの配列リファレンスに分割(端数は切り捨て)

で、テストから書きました。

#!/usr/bin/env perl
use strict;
use warnings;
use FindBin;
use lib "$FindBin::Bin/../lib";
use Test::More tests => 2;

BEGIN {use_ok('MyArrayUtility')}

# MyArrayUtility::divide_arrayのテスト
my @arr = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);
my $arr_ref = \@arr;
my $item_number_in_list = 4;
my $divided_arr_ref = MyArrayUtility::divide_array($arr_ref, $item_number_in_list);
my $expected = [
    [ 1, 2, 3, 4 ],
    [ 5, 6, 7, 8 ],
    [ 9, 10, 11, 12 ]
];
is_deeply($divided_arr_ref, $expected, 'divide_array');


実処理部分はこんな感じで。

package MyArrayUtility;

use strict;
use warnings;
use utf8;

# 配列を指定した要素数ごとに別の配列に分割する処理
sub divide_array {
    my ($arr_ref, $item_number_in_list) = @_;
    my $count = @$arr_ref;

    # スライスしてできる配列の数(端数は切り捨て)
    my $array_num = int($count / $item_number_in_list);

    # 結果を格納する配列リファレンス
    my $divided_arr_ref = [];

    my $i = 0;
    my $j = 0;
    while ($i < $array_num) {
        while ($j < $item_number_in_list) {
            push(@{$divided_arr_ref->[$i]}, shift(@$arr_ref));
            $j++;
        }
        $i++;
        $j = 0;
    }

    return $divided_arr_ref;
}


1;

ディレクトリ構成はこんな感じで慣習通りに。

C:.
+---lib
|       MyArrayUtility.pm
|
\---t
        my_array_utility.t

なんか、もう少しスマートに書ける気がするけど、とりあえず要件は満たしているのでOKかな。

リファレンスがやっとわかり始めてきました。