map と grep の違い ~ 一目瞭然編 ~

my $array_ref = [
^---{id => 1, name => 'hoge', atk => 5, def => 8, hp => 10},
^---{id => 2, name => 'fuga', atk => 6, def => 9, hp => 13},
^---{id => 3, name => 'foo', atk => 7, def => 10, hp => 18},
^---{id => 4, name => 'aaa', atk => 8, def => 19, hp => 13},
^---{id => 5, name => 'aaa', atk => 8, def => 19, hp => 13},
^---{id => 6, name => 'aaa', atk => 8, def => 19, hp => 13},
^---{id => 7, name => 'aaa', atk => 8, def => 19, hp => 13},
^---{id => 8, name => 'bbb', atk => 9, def => 2, hp => 20},
^---{id => 9, name => 'bbb', atk => 9, def => 2, hp => 20},
^---{id => 10, name => 'bbb', atk => 9, def => 2, hp => 20},
^---{id => 11, name => 'bbb', atk => 9, def => 2, hp => 20},
];

my @map_array = map {$_->{atk}} @$array_ref;
my @grep_array = grep {$_->{atk}} @$array_ref;

print Dumper(\@map_array);
print Dumper(\@grep_array);

結果は当然こんなかんじに.

[map]
$VAR1 = [
5,
6,
7,
8,
8,
8,
8,
9,
9,
9,
9
];

map は配列に操作します.

一方, grep は,

[grep]
$VAR1 = [
{
'hp' => 10,
'def' => 8,
'atk' => 5,
'name' => 'hoge',
'id' => 1
},
{
'hp' => 13,
'def' => 9,
'atk' => 6,
'name' => 'fuga',
'id' => 2
},
{
'hp' => 18,
'def' => 10,
'atk' => 7,
'name' => 'foo',
'id' => 3
},
{
'hp' => 13,
'def' => 19,
'atk' => 8,
'name' => 'aaa',
'id' => 4
},
{
'hp' => 13,
'def' => 19,
'atk' => 8,
'name' => 'aaa',
'id' => 5
},
......つづく

つまり, 配列に何も操作しません.
そのまま全部垂れ流します.
grep はスクリーニングするのでした.(配列の長さが変えられます.)
よって正しい使用方法はこんなかんじ.

my @grep_array = grep {$_->{atk} > 8} @$array_ref;

Dumperで出力するとこんなかんじに.

$VAR1 = [
{
'hp' => 20,
'def' => 2,
'atk' => 9,
'name' => 'bbb',
'id' => 8
},
{
'hp' => 20,
'def' => 2,
'atk' => 9,
'name' => 'bbb',
'id' => 9
},
{
'hp' => 20,
'def' => 2,
'atk' => 9,
'name' => 'bbb',
'id' => 10
},
{
'hp' => 20,
'def' => 2,
'atk' => 9,
'name' => 'bbb',
'id' => 11
}
];