特定の項目でソートする - Perl

以下のような配列がある時、2番目の項目で並べ替えがしたい。 単純に sort @array しただけではできない。

@array = ( '1,b,c'
             , '3,c,b'
             , '2,a,a'
);

ソート項目が数値の時にはorderByArrayNum、文字列の時にはorderByArrayStrをそれぞれ呼び出せば良い。配列そのものの値が変わるので、オリジナルを保存しておきたい場合には、必ずコピーを渡すこと。

サンプル

;#
;#特定の項目でソートする
;#

use strict;

{
  my @array = ( '1,c,A'
         , '3,b,B'
         , '2,a,C'
  );

  #-- 並べ替え(文字列) --#
  orderByArrayStr(
        \@array    #対象配列
         , 1    #ソートするキー(0,1, ... n)
         , 'ASC'  #ASC:昇順、DESC:降順
  );

  print "$_\n" foreach( @array );
  print "\n";

  #-- 並べ替え(数値) --#
  orderByArrayNum(
        \@array    #対象配列
         , 0    #ソートするキー(0,1, ... n)
         , 'DESC'  #ASC:昇順、DESC:降順
  );

  print "$_\n" foreach( @array );
  print "\n";
}


#----------------------
#数値ソート
#----------------------
sub orderByArrayNum{
  my $data = shift;      #配列の参照
  my $key = shift || 0;    #ソートするキー
  my $set = shift || 'DESC';  #昇順or降順
  my @tmp = ();

  #-- 一時配列にキーを取り出す --#
  @tmp = map {(split /,/)[$key]} @$data;

  #-- ソート開始 --#
  if( $set eq 'ASC' ){
    @$data = @$data[sort {$tmp[$a] <=> $tmp[$b]} 0 .. $#tmp];
  }
  else{
    @$data = @$data[sort {$tmp[$b] <=> $tmp[$a]} 0 .. $#tmp];
  }

}


#----------------------
#文字列ソート
#----------------------
sub orderByArrayStr{
  my $data = shift;      #配列の参照
  my $key = shift || 0;    #ソートするキー
  my $set = shift || 'DESC';  #昇順or降順
  my @tmp = ();

  #-- 一時配列にキーを取り出す --#
  @tmp = map {(split /,/)[$key]} @$data;

  #-- ソート開始 --#
  if( $set eq 'ASC' ){
    @$data = @$data[sort {$tmp[$a] cmp $tmp[$b]} 0 .. $#tmp];
  }
  else{
    @$data = @$data[sort {$tmp[$b] cmp $tmp[$a]} 0 .. $#tmp];
  }

}

実行結果

2,a,C
3,b,B
1,c,A
3,b,B
2,a,C
1,c,A

参考