[PHP]rsort関数の使い方を徹底解説!逆順ソートをマスター

PHP

PHPで配列をソートする際、降順(大きい順)に並べ替えたい場面がよくあります。ランキング表示、新しい順の並び替え、価格の高い順など、様々な用途で逆順ソートが必要です。この記事では、PHPのrsort関数について、基本的な使い方から実践的な活用方法まで詳しく解説していきます。

rsort関数とは?

rsortは、配列を降順(大きい順)にソートする関数です。元の配列を直接変更し、キーと値の関連付けは失われます。

基本的な構文

bool rsort(array &$array, int $flags = SORT_REGULAR)

パラメータ:

  • $array: ソートする配列(参照渡し)
  • $flags: ソート方法を指定するフラグ

戻り値:

  • 成功時: true
  • 失敗時: false

重要: 配列は参照渡しされ、元の配列が変更されます。キーは0から振り直されます。

ソートフラグ

フラグ説明
SORT_REGULAR通常の比較(デフォルト)
SORT_NUMERIC数値として比較
SORT_STRING文字列として比較
SORT_LOCALE_STRINGロケールに基づいて文字列比較
SORT_NATURAL自然順ソート
SORT_FLAG_CASE大文字小文字を区別しない(他のフラグと組み合わせ)

基本的な使い方

数値の降順ソート

<?php
$numbers = [3, 1, 4, 1, 5, 9, 2, 6];

rsort($numbers);
print_r($numbers);
// Array ( [0] => 9 [1] => 6 [2] => 5 [3] => 4 [4] => 3 [5] => 2 [6] => 1 [7] => 1 )

// 元の配列が変更される
echo "最大値: " . $numbers[0] . "\n";  // 9
echo "最小値: " . $numbers[count($numbers) - 1] . "\n";  // 1
?>

文字列の降順ソート

<?php
$fruits = ['apple', 'banana', 'cherry', 'date', 'elderberry'];

rsort($fruits);
print_r($fruits);
// Array ( [0] => elderberry [1] => date [2] => cherry [3] => banana [4] => apple )

// アルファベット逆順(Z→A)
?>

連想配列での注意点

<?php
$assoc = ['a' => 3, 'b' => 1, 'c' => 2];

echo "ソート前:\n";
print_r($assoc);

rsort($assoc);

echo "ソート後:\n";
print_r($assoc);
// Array ( [0] => 3 [1] => 2 [2] => 1 )
// キーが失われて数値インデックスに

// ✅ キーを保持したい場合はarsort()を使用
$assoc2 = ['a' => 3, 'b' => 1, 'c' => 2];
arsort($assoc2);
print_r($assoc2);
// Array ( [a] => 3 [c] => 2 [b] => 1 )
?>

他のソート関数との違い

ソート関数の比較

<?php
$numbers = [3, 1, 4, 1, 5, 9, 2, 6];

// sort() - 昇順、キーを振り直す
$arr1 = $numbers;
sort($arr1);
echo "sort: " . implode(', ', $arr1) . "\n";
// 1, 1, 2, 3, 4, 5, 6, 9

// rsort() - 降順、キーを振り直す
$arr2 = $numbers;
rsort($arr2);
echo "rsort: " . implode(', ', $arr2) . "\n";
// 9, 6, 5, 4, 3, 2, 1, 1

// asort() - 昇順、キーを保持
$arr3 = ['a' => 3, 'b' => 1, 'c' => 2];
asort($arr3);
echo "asort: ";
foreach ($arr3 as $k => $v) echo "$k=>$v ";
echo "\n";
// b=>1 c=>2 a=>3

// arsort() - 降順、キーを保持
$arr4 = ['a' => 3, 'b' => 1, 'c' => 2];
arsort($arr4);
echo "arsort: ";
foreach ($arr4 as $k => $v) echo "$k=>$v ";
echo "\n";
// a=>3 c=>2 b=>1
?>

比較表

関数順序キー保持用途
sort()昇順値のみの配列
rsort()降順値のみの配列
asort()昇順連想配列
arsort()降順連想配列
ksort()昇順キーでソート
krsort()降順キーでソート
usort()カスタムカスタム比較
uasort()カスタムカスタム比較

実践的な使用例

1. ランキング表示

<?php
/**
 * ランキング生成クラス
 */
class RankingGenerator {
    
    /**
     * スコアランキングを生成
     */
    public static function generateScoreRanking($players) {
        // スコアを抽出
        $scores = array_column($players, 'score');
        
        // 降順ソート(元の配列は保持)
        $sortedScores = $scores;
        rsort($sortedScores);
        
        $ranking = [];
        
        foreach ($sortedScores as $rank => $score) {
            // 同じスコアのプレイヤーを検索
            foreach ($players as $player) {
                if ($player['score'] === $score && 
                    !in_array($player['name'], array_column($ranking, 'name'))) {
                    $ranking[] = [
                        'rank' => $rank + 1,
                        'name' => $player['name'],
                        'score' => $score
                    ];
                    break;
                }
            }
        }
        
        return $ranking;
    }
    
    /**
     * トップN件を取得
     */
    public static function getTopN($values, $n = 10) {
        $sorted = $values;
        rsort($sorted);
        return array_slice($sorted, 0, $n);
    }
    
    /**
     * ランキング表を表示
     */
    public static function displayRanking($ranking) {
        echo "順位  名前              スコア\n";
        echo str_repeat("-", 40) . "\n";
        
        foreach ($ranking as $entry) {
            printf(
                "%-4d  %-16s  %6d\n",
                $entry['rank'],
                $entry['name'],
                $entry['score']
            );
        }
    }
}

// 使用例
echo "=== スコアランキング ===\n";

$players = [
    ['name' => '太郎', 'score' => 8500],
    ['name' => '花子', 'score' => 9200],
    ['name' => '次郎', 'score' => 7800],
    ['name' => '美咲', 'score' => 9500],
    ['name' => '健太', 'score' => 8200]
];

$ranking = RankingGenerator::generateScoreRanking($players);
RankingGenerator::displayRanking($ranking);

echo "\n=== トップ3 ===\n";
$scores = array_column($players, 'score');
$top3 = RankingGenerator::getTopN($scores, 3);
echo "トップ3のスコア: " . implode(', ', $top3) . "\n";
?>

2. 価格順の商品表示

<?php
/**
 * 商品ソートクラス
 */
class ProductSorter {
    
    /**
     * 価格が高い順にソート
     */
    public static function sortByPriceDesc($products) {
        $sorted = $products;
        
        usort($sorted, function($a, $b) {
            return $b['price'] - $a['price'];
        });
        
        return $sorted;
    }
    
    /**
     * 価格が安い順にソート
     */
    public static function sortByPriceAsc($products) {
        $sorted = $products;
        
        usort($sorted, function($a, $b) {
            return $a['price'] - $b['price'];
        });
        
        return $sorted;
    }
    
    /**
     * 評価が高い順にソート
     */
    public static function sortByRatingDesc($products) {
        $sorted = $products;
        
        usort($sorted, function($a, $b) {
            return $b['rating'] <=> $a['rating'];
        });
        
        return $sorted;
    }
    
    /**
     * 価格帯でフィルタリングしてソート
     */
    public static function filterAndSort($products, $minPrice, $maxPrice) {
        $filtered = array_filter($products, function($product) use ($minPrice, $maxPrice) {
            return $product['price'] >= $minPrice && $product['price'] <= $maxPrice;
        });
        
        return self::sortByPriceDesc($filtered);
    }
    
    /**
     * 商品リストを表示
     */
    public static function display($products, $title = '商品一覧') {
        echo "\n=== {$title} ===\n";
        
        foreach ($products as $i => $product) {
            printf(
                "%d. %s - ¥%s (評価: %.1f)\n",
                $i + 1,
                $product['name'],
                number_format($product['price']),
                $product['rating']
            );
        }
    }
}

// 使用例
$products = [
    ['name' => 'ノートPC', 'price' => 89800, 'rating' => 4.5],
    ['name' => 'マウス', 'price' => 2980, 'rating' => 4.2],
    ['name' => 'キーボード', 'price' => 8900, 'rating' => 4.7],
    ['name' => 'モニター', 'price' => 35800, 'rating' => 4.4],
    ['name' => 'Webカメラ', 'price' => 5400, 'rating' => 4.0]
];

ProductSorter::display(
    ProductSorter::sortByPriceDesc($products),
    '価格が高い順'
);

ProductSorter::display(
    ProductSorter::sortByPriceAsc($products),
    '価格が安い順'
);

ProductSorter::display(
    ProductSorter::sortByRatingDesc($products),
    '評価が高い順'
);

ProductSorter::display(
    ProductSorter::filterAndSort($products, 5000, 50000),
    '¥5,000〜¥50,000の商品(価格が高い順)'
);
?>

3. 日付・時刻のソート

<?php
/**
 * 日付ソートクラス
 */
class DateSorter {
    
    /**
     * 日付文字列を新しい順にソート
     */
    public static function sortDatesDesc($dates) {
        $timestamps = array_map('strtotime', $dates);
        rsort($timestamps);
        
        return array_map(function($ts) {
            return date('Y-m-d', $ts);
        }, $timestamps);
    }
    
    /**
     * イベントを日付順にソート
     */
    public static function sortEventsByDate($events, $descending = true) {
        $sorted = $events;
        
        usort($sorted, function($a, $b) use ($descending) {
            $timeA = strtotime($a['date']);
            $timeB = strtotime($b['date']);
            
            return $descending ? $timeB - $timeA : $timeA - $timeB;
        });
        
        return $sorted;
    }
    
    /**
     * 最新のN件を取得
     */
    public static function getLatest($items, $dateKey, $n = 5) {
        $sorted = $items;
        
        usort($sorted, function($a, $b) use ($dateKey) {
            return strtotime($b[$dateKey]) - strtotime($a[$dateKey]);
        });
        
        return array_slice($sorted, 0, $n);
    }
    
    /**
     * 期間内のアイテムを取得
     */
    public static function getItemsInPeriod($items, $dateKey, $startDate, $endDate) {
        $start = strtotime($startDate);
        $end = strtotime($endDate);
        
        $filtered = array_filter($items, function($item) use ($dateKey, $start, $end) {
            $itemDate = strtotime($item[$dateKey]);
            return $itemDate >= $start && $itemDate <= $end;
        });
        
        return self::sortEventsByDate($filtered, true);
    }
}

// 使用例
echo "\n=== 日付ソート ===\n";

$dates = ['2024-03-15', '2024-01-20', '2024-05-10', '2024-02-28'];
$sorted = DateSorter::sortDatesDesc($dates);
echo "日付(新しい順): " . implode(', ', $sorted) . "\n";

echo "\n=== イベント一覧 ===\n";
$events = [
    ['title' => 'セミナーA', 'date' => '2024-03-15'],
    ['title' => 'ワークショップB', 'date' => '2024-01-20'],
    ['title' => 'カンファレンスC', 'date' => '2024-05-10'],
    ['title' => 'ミートアップD', 'date' => '2024-02-28']
];

$sortedEvents = DateSorter::sortEventsByDate($events, true);
foreach ($sortedEvents as $event) {
    echo "{$event['date']}: {$event['title']}\n";
}

echo "\n=== 最新3件のニュース ===\n";
$news = [
    ['title' => 'ニュース1', 'published' => '2024-01-15'],
    ['title' => 'ニュース2', 'published' => '2024-01-20'],
    ['title' => 'ニュース3', 'published' => '2024-01-10'],
    ['title' => 'ニュース4', 'published' => '2024-01-25'],
    ['title' => 'ニュース5', 'published' => '2024-01-18']
];

$latest = DateSorter::getLatest($news, 'published', 3);
foreach ($latest as $item) {
    echo "{$item['published']}: {$item['title']}\n";
}
?>

4. 数値データの分析

<?php
/**
 * データ分析クラス
 */
class DataAnalyzer {
    
    /**
     * 上位N件の値を取得
     */
    public static function topN($data, $n = 10) {
        $sorted = $data;
        rsort($sorted);
        return array_slice($sorted, 0, $n);
    }
    
    /**
     * 下位N件の値を取得
     */
    public static function bottomN($data, $n = 10) {
        $sorted = $data;
        sort($sorted);
        return array_slice($sorted, 0, $n);
    }
    
    /**
     * パーセンタイル値を計算
     */
    public static function percentile($data, $percentile) {
        $sorted = $data;
        rsort($sorted);
        
        $index = ceil((count($sorted) * $percentile) / 100) - 1;
        $index = max(0, min($index, count($sorted) - 1));
        
        return $sorted[$index];
    }
    
    /**
     * 外れ値を検出
     */
    public static function detectOutliers($data) {
        $sorted = $data;
        rsort($sorted);
        
        $q1 = self::percentile($sorted, 25);
        $q3 = self::percentile($sorted, 75);
        $iqr = $q3 - $q1;
        
        $lowerBound = $q1 - 1.5 * $iqr;
        $upperBound = $q3 + 1.5 * $iqr;
        
        $outliers = array_filter($data, function($value) use ($lowerBound, $upperBound) {
            return $value < $lowerBound || $value > $upperBound;
        });
        
        rsort($outliers);
        
        return [
            'outliers' => $outliers,
            'lower_bound' => $lowerBound,
            'upper_bound' => $upperBound
        ];
    }
    
    /**
     * データサマリーを生成
     */
    public static function summarize($data) {
        $sorted = $data;
        rsort($sorted);
        
        return [
            'count' => count($data),
            'max' => $sorted[0] ?? null,
            'min' => $sorted[count($sorted) - 1] ?? null,
            'mean' => count($data) > 0 ? array_sum($data) / count($data) : 0,
            'median' => self::percentile($data, 50),
            'top_10_percent' => self::topN($data, max(1, ceil(count($data) * 0.1))),
            'bottom_10_percent' => self::bottomN($data, max(1, ceil(count($data) * 0.1)))
        ];
    }
}

// 使用例
echo "\n=== データ分析 ===\n";

$salesData = [
    1200, 3400, 2100, 5600, 1800, 4200, 3100, 2800, 1500, 3900,
    2400, 4800, 2200, 3500, 1900, 4500, 2700, 3300, 2000, 4100
];

echo "上位5件: " . implode(', ', DataAnalyzer::topN($salesData, 5)) . "\n";
echo "下位5件: " . implode(', ', DataAnalyzer::bottomN($salesData, 5)) . "\n";

echo "\n75パーセンタイル: " . DataAnalyzer::percentile($salesData, 75) . "\n";
echo "50パーセンタイル(中央値): " . DataAnalyzer::percentile($salesData, 50) . "\n";
echo "25パーセンタイル: " . DataAnalyzer::percentile($salesData, 25) . "\n";

echo "\n外れ値検出:\n";
$outlierData = [10, 12, 11, 13, 12, 14, 11, 15, 12, 100, 11, 13];
$outliers = DataAnalyzer::detectOutliers($outlierData);
echo "外れ値: " . implode(', ', $outliers['outliers']) . "\n";
echo "下限: {$outliers['lower_bound']}, 上限: {$outliers['upper_bound']}\n";

echo "\nデータサマリー:\n";
$summary = DataAnalyzer::summarize($salesData);
echo "件数: {$summary['count']}\n";
echo "最大: {$summary['max']}\n";
echo "最小: {$summary['min']}\n";
echo "平均: " . round($summary['mean'], 2) . "\n";
echo "中央値: {$summary['median']}\n";
echo "上位10%: " . implode(', ', $summary['top_10_percent']) . "\n";
?>

5. ファイルサイズのソート

<?php
/**
 * ファイルソートクラス
 */
class FileSorter {
    
    /**
     * ファイルサイズでソート
     */
    public static function sortBySize($files, $descending = true) {
        $sorted = $files;
        
        usort($sorted, function($a, $b) use ($descending) {
            $comparison = $b['size'] - $a['size'];
            return $descending ? $comparison : -$comparison;
        });
        
        return $sorted;
    }
    
    /**
     * バイトを読みやすい形式に変換
     */
    public static function formatBytes($bytes) {
        $units = ['B', 'KB', 'MB', 'GB', 'TB'];
        $bytes = max($bytes, 0);
        $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
        $pow = min($pow, count($units) - 1);
        $bytes /= pow(1024, $pow);
        
        return round($bytes, 2) . ' ' . $units[$pow];
    }
    
    /**
     * 最大のN個のファイルを取得
     */
    public static function getLargestFiles($files, $n = 10) {
        $sorted = self::sortBySize($files, true);
        return array_slice($sorted, 0, $n);
    }
    
    /**
     * ファイルリストを表示
     */
    public static function display($files) {
        echo str_repeat("-", 60) . "\n";
        printf("%-40s %15s\n", "ファイル名", "サイズ");
        echo str_repeat("-", 60) . "\n";
        
        foreach ($files as $file) {
            printf(
                "%-40s %15s\n",
                $file['name'],
                self::formatBytes($file['size'])
            );
        }
    }
}

// 使用例
echo "\n=== ファイルサイズソート ===\n";

$files = [
    ['name' => 'document.pdf', 'size' => 2456789],
    ['name' => 'image.jpg', 'size' => 456123],
    ['name' => 'video.mp4', 'size' => 125678900],
    ['name' => 'archive.zip', 'size' => 8901234],
    ['name' => 'data.csv', 'size' => 123456]
];

echo "サイズが大きい順:\n";
FileSorter::display(FileSorter::sortBySize($files, true));

echo "\n最も大きい3ファイル:\n";
FileSorter::display(FileSorter::getLargestFiles($files, 3));
?>

よくある間違いと注意点

間違い1: キーの保持を期待

<?php
// ❌ rsortはキーを保持しない
$assoc = ['b' => 20, 'a' => 30, 'c' => 10];
rsort($assoc);
// キーが失われる: [0 => 30, 1 => 20, 2 => 10]

// ✅ キーを保持するにはarsort()
$assoc2 = ['b' => 20, 'a' => 30, 'c' => 10];
arsort($assoc2);
// キーが保持される: ['a' => 30, 'b' => 20, 'c' => 10]
?>

間違い2: 数値と文字列の混在

<?php
$mixed = ['10', 2, '100', 20];

// デフォルトは文字列比較
rsort($mixed);
print_r($mixed);
// 予期しない結果の可能性

// ✅ 数値として明示的にソート
rsort($mixed, SORT_NUMERIC);
print_r($mixed);
// ['100', 20, '10', 2]
?>

間違い3: 元の配列が変更されることを忘れる

<?php
$original = [3, 1, 4, 1, 5];

// ❌ 元の配列が変更される
rsort($original);
// $originalは変更されている

// ✅ コピーを作成してソート
$original = [3, 1, 4, 1, 5];
$sorted = $original;
rsort($sorted);
// $originalは変更されていない
?>

まとめ

rsort関数は、PHPで配列を降順にソートするための基本的な関数です。以下のポイントを押さえておきましょう。

  • **降順(大きい順)**に配列をソート
  • 元の配列を直接変更する(参照渡し)
  • キーは失われて0から振り直される
  • SORT_NUMERICSORT_STRINGなどのフラグで挙動を制御
  • ランキング、価格順、日付順の表示に活用
  • **キーを保持したい場合はarsort()**を使用
  • 数値と文字列の混在に注意
  • データ分析や統計処理に便利

rsortを適切に使うことで、データを効果的に降順で表示・処理できます。用途に応じて他のソート関数と使い分けましょう!

タイトルとURLをコピーしました