@blog.justoneplanet.info

日々勉強

PHP Sorting Arrays(配列のソート)

■配列の値によるソート(0から始まる数値インデックスに直す)

以下のように、sort関数を使うと値をアルファベット順にソートし、インデックスを振りなおす。また第二引数にはSORT_REGULAR、SORT_NUMERIC、SORT_STRINGなどを取り、型を変換する事もできる。

<?php
$tmpAry = array(
    'person1' => 'Emily',
    'person2' => 'Dennis',
    'person3' => 'Andy'
);
sort($tmpAry);
var_dump($tmpAry);
/*
array(3) {
  [0]=>
  string(4) "Andy"
  [1]=>
  string(6) "Dennis"
  [2]=>
  string(5) "Emily"
}
*/
?>

逆順にソートするには

以下のようにrsort関数を使用すると、sort関数を使った時とは逆順に並ぶ。

<?php
$tmpAry = array(
    'person1' => 'Andy',
    'person2' => 'Dennis',
    'person3' => 'Emily'
);
rsort($tmpAry);
var_dump($tmpAry);
/*
array(3) {
  [0]=>
  string(5) "Emily"
  [1]=>
  string(6) "Dennis"
  [2]=>
  string(4) "Andy"
}
*/
?>

戻り値について

以下の例のようにsort関数は配列自身を変換し、戻り値は処理の成否についてのbool値が格納されるだけである。基本的に配列ソート関数は全て配列自身を変換し、戻り値は処理の成否としてのbool値となる。

<?php
var_dump(sort($tmpAry));//true or false
?>

ユーザー指定関数での並び替え

以下のようにusort関数を使用する。第二引数には文字列で関数名を指定する。(但し、以下の例はグローバル空間が汚れないように、create_function関数を使っての匿名関数を利用している。)

<?php
$ary = array(1, 5, 2);
usort(
    $ary,
    create_function(
        '$a,$b',
        'if($a < $b){return 1;}if($a === $b){return 0;}if($a > $b){return -1;}'
    )
);
var_dump($ary);
/*
array(3) {
  [0]=>
  int(5)
  [1]=>
  int(2)
  [2]=>
  int(1)
}
*/
?>

■配列の値によるソート(キーとの関係は維持)

以下のようにasort関数を使うとキーとの関係は維持されつつ、値によるソートが行われる。

<?php
$tmpAry = array(
    'person1' => 'Emily',
    'person2' => 'Dennis',
    'person3' => 'Andy'
);
asort($tmpAry);
var_dump($tmpAry);
/*
array(3) {
  ["person3"]=>
  string(4) "Andy"
  ["person2"]=>
  string(6) "Dennis"
  ["person1"]=>
  string(5) "Emily"
}
*/
?>

逆順にしたい時にはarsort関数を使用し、ユーザー定義関数でソートしたいときにはuasort関数を使用する。但し、今考える限りではキーとの関係を維持したままソートする有用なシチュエーションは思い浮かばない。

■配列のキーによるソート

以下のようにksort関数を使うと、配列のキーによってソートされる。

<?php
$tmpAry = array(
    'Naomi' => 'student',
    'Dennis' => 'driver',
    'Emily' => 'traveler'
);
ksort($tmpAry);
var_dump($tmpAry);
/*
array(3) {
  ["Dennis"]=>
  string(6) "driver"
  ["Emily"]=>
  string(8) "traveler"
  ["Naomi"]=>
  string(7) "student"
}
*/
?>

また、逆順にしたい時はkrsort関数を使い、ユーザー定義関数でソートしたい時はuksort関数を使う。

PHPは内部的に配列のキーとは別に順序を持っている。内部順序とキーの順序が違う場合、json_encode関数を使うと変換が異なるので注意しなくてはならない。

<?php
$tmpAry = array(
    2 => 'Naomi',
    1 => 'Dennis',
    0 => 'Emily'
);
var_dump($tmpAry);
ksort($tmpAry);
var_dump($tmpAry);
/*
array(3) {
  [2]=>
  string(5) "Naomi"
  [1]=>
  string(6) "Dennis"
  [0]=>
  string(5) "Emily"
}
string(38) "{"2":"Naomi","1":"Dennis","0":"Emily"}"
array(3) {
  [0]=>
  string(5) "Emily"
  [1]=>
  string(6) "Dennis"
  [2]=>
  string(5) "Naomi"
}
string(26) "["Emily","Dennis","Naomi"]"
*/
?>

■まとめ

一覧にまとめると以下のようになる。

処理 昇順 降順 ユーザー定義
値によるソート、インデックスの再ラベリング sort rsort usort
値によるソート asort arsort uasort
キーによるソート ksort krsort uksort

個人的な考えだが「昇順と降順」は引数でコントロールできるようにしてもイイと思う。

ユーザー定義関数について

<?php
$ary = array(1, 5, 2);
usort(
    $ary,
    create_function(
        '$a,$b',
        'if($a < $b){return 1;}if($a === $b){return 0;}if($a > $b){return -1;}'
    )
);
var_dump($ary);
/*
array(3) {
  [0]=>
  int(5)
  [1]=>
  int(2)
  [2]=>
  int(1)
}
*/
?>
  • 引数を2つとる
  • 「if($a < $b){return 1;}」は「$a<$b」の時、そのままの順序である事を意味する。
  • 「if($a > $b){return -1;}」は「$a>$b」の時、前後を入れ替える事を意味する。
  • 「if($a === $b){return 0;}」は「$a === $b」の時、特に何もしない事を意味する。

つまり、比較関数は最初の引数が2番目の引数より小さいか、等しいか、大きい場合に、 それぞれゼロ未満、ゼロに等しい、ゼロより大きい整数を返す。

■自然順ソート

通常のソート関数を使うと、以下のように不自然な結果となる。

<?php
$tmpAry = array('10km', '5km', '7km');
sort($tmpAry);
var_dump($tmpAry);
/*
array(3) {
  [0]=>
  string(4) "10km"
  [1]=>
  string(3) "5km"
  [2]=>
  string(3) "7km"
}
*/
?>

以下のようにnatsort関数を使用すると、数字+単位のように扱われ、自然な並び順となる。また、大文字と小文字を区別しないnatcasesort関数もある。

<?php
$tmpAry = array('10km', '5km', '7km');
natsort($tmpAry);
var_dump($tmpAry);
/*
array(3) {
  [1]=>
  string(3) "5km"
  [2]=>
  string(3) "7km"
  [0]=>
  string(4) "10km"
}
*/
?>

各関数について

bool natsort(array &$ary)
自然順で配列をソートする。
bool natcasesort(array &$ary)
大文字と小文字を区別しない自然順アルゴリズムでソートする。

■配列のシャッフル

以下のようにshuffle関数を使うと、配列をランダムに並び替えることができる。以下の結果は実行ごとに異なるが、キーは必ず削除され数値のインデックスが割り当てられる。

<?php
$tmpAry = array(
    'person1' => 'Emily',
    'person2' => 'Dennis',
    'person3' => 'Andy'
);
shuffle($tmpAry);
/*
array(3) {
  [0]=>
  string(6) "Dennis"
  [1]=>
  string(5) "Emily"
  [2]=>
  string(4) "Andy"
}
*/
?>

各巻数について

bool shuffle(array &$ary)
配列をシャッフルする。但し、既存のキーは削除される。

コメントはまだありません»

No comments yet.

RSS feed for comments on this post.TrackBack URL

Leave a comment