Perlの配列ソート学習ノート
この記事では、Perlで文字列や数値の配列をソートする方法について学びます。
Perlにはsortという組み込み関数があり、間違いなく配列をソートすることができます。最も単純な形では、配列を渡すと、ソートされた要素の配列が返されます。sort = sort @original。
ASCIIコードに基づくソート
#! /usr/bin/perl
use strict;
use warnings;
use 5.010;
use Data::Dumper qw(Dumper);
my @words = qw(foo bar zorg moo);
say Dumper \@words;
my @sorted_words = sort @words;
say Dumper \@sorted_words;
上記の例では、次のように表示されます。
$VAR1 = [
'foo',
'bar',
'zorg',
'moo'
];
$VAR1 = [
'bar',
'foo',
'moo',
'zorg'
];
最初の出力はソート前の配列、2番目はソート後の配列を表しています。
これは最も単純なケースですが、あなたが望むものとは異なるかもしれません。例えば、ある単語が大文字で始まる場合はどうでしょう?
my @words = qw(foo bar Zorg moo);
The result in @sorted_names will be.
$VAR1 = [
'Zorg',
'bar',
'foo',
'moo'
];
大文字で始まる単語が先に来ていることにお気づきでしょうか。これは、sort がデフォルトで ASCII テーブルに従ってソートされ、すべての大文字が小文字の前に来るからです。
比較機能
Perlのソートの仕組みは、元の配列の2つの要素それぞれについて、左側の値を変数$aに、右側の値を変数$bに入れるという反復処理を行います。そして、compare関数を呼び出します。compare関数"は、$aの内容が左であれば1、$bの内容が左であれば-1、両者が同じであれば0を返します。
通常は比較関数を見ずに、sortがASCIIテーブルと値を比較しますが、必要であれば明示的に記述することができます。
sort { $a cmp $b } @words;
このコードは、ブロックなしで@wordsを並べ替えるのと同じ効果を得ることができます。
ここで、perlがデフォルトで比較関数としてcmpを使用していることがわかります。これは、cmpがここで必要なことを正確に実行してくれるからです。2つの文字列の値を比較し、左の引数が右の引数より小さければ1、左の引数が右の引数より大きければ-1、そして等しければ0を返します。
アルファベット順
文字列の大文字と小文字を無視して並べ替えたい場合、つまり一般にアルファベット順と呼ばれるものは、次の例のようにすることができます。
my @sorted_words = sort { lc($a) cmp lc($b) } @words;
ここでは、比較のために、lc関数を呼び出して、引数の小文字版を返しています。そして、cmpはこれらの小文字版を比較して、元の文字列の中で誰が1番目で、誰が2番目かを判断する。
その結果は
$VAR1 = [
'bar',
'foo',
'moo',
'Zorg'
];
Perl による値の並べ替え
数値配列に対してデフォルトでソートを使用すると、期待した結果にならない場合があります。
my @numbers = (14, 3, 12, 2, 23);
my @sorted_numbers = sort @numbers;
say Dumper \@sorted_numbers;
$VAR1 = [
12,
14,
2,
23,
3
考えてみれば、これは驚くべきことではない。compare関数は12と3を見たとき、文字列で比較します。つまり、2つの文字列 "1" と "3" の最初の文字を比較するわけです。ASCIIテーブルでは、"1"が"3"の前に来るので、文字列 "12" は文字列 "3" の前に来ることになるのです。
Perlは、あなたがこれらの値を数字でソートしたいことを魔法のように推測するわけではありません。
2つの値を数値で比較する比較関数を書くことはできますが。しかしここでは、2つの引数を数値で比較して1、-1、0を返す<=>(スペースシップ演算子としても知られている)を使っています。
my @sorted_numbers = sort { $a <=> $b } @numbers;
という結果になります。
$VAR1 = [
2,
3,
12,
14,
23
];
関連
-
perlの文字列操作関数chompとchopの紹介
-
Perl オブジェクト指向の例
-
PerlによるMSSQLへのアクセスとMySQLデータベースへの移行スクリプト例
-
perl で書かれた乱数話法プログラム (rand random function)
-
perl変数$/の使用方法について説明します。コンテキストが行モードのとき、$/は行を区別するものを定義します。
-
コンストラクタでのPerlメソッド使用法入門
-
[解決済み] Perlからsedを使うには?
-
[解決済み] Perl で bash コマンドを使用して文字列をエコーするにはどうすればよいですか?
-
[解決済み] Hashに重複したキーや値を持たせることができるか
-
[解決済み] Perlでディレクトリを丸ごとコピーするにはどうしたらいいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン