Navigation

Php

How to Sort Arrays by Key and Value

Master PHP array sorting with built-in functions for organizing data by values, keys, or custom criteria using sort(), asort(), ksort(), and usort().

Table Of Contents

The Fix

Array sorting organizes data for better presentation and processing. PHP provides different sorting functions depending on whether you want to sort by values, keys, or maintain key-value associations, each with specific use cases for different data structures.

<?php

// Basic value sorting
$numbers = [5, 2, 8, 1, 9, 3];

// Sort values, renumber keys
sort($numbers);
// Result: [1, 2, 3, 5, 8, 9] with keys [0, 1, 2, 3, 4, 5]

// Sort values, maintain key associations
$scores = ['Alice' => 95, 'Bob' => 87, 'Charlie' => 92, 'Diana' => 89];
asort($scores);
// Result: ['Bob' => 87, 'Diana' => 89, 'Charlie' => 92, 'Alice' => 95]

// Reverse value sort
arsort($scores);
// Result: ['Alice' => 95, 'Charlie' => 92, 'Diana' => 89, 'Bob' => 87]

// Sort by keys
$data = ['zebra' => 1, 'apple' => 2, 'banana' => 3];
ksort($data);
// Result: ['apple' => 2, 'banana' => 3, 'zebra' => 1]

// Reverse key sort
krsort($data);
// Result: ['zebra' => 1, 'banana' => 3, 'apple' => 2]

// Case-insensitive sorting
$words = ['Zebra', 'apple', 'Banana', 'Cherry'];
natcasesort($words);
// Result: Natural order, case-insensitive

// Real-world examples

// Sort products by price
$products = [
    ['name' => 'Laptop', 'price' => 999, 'category' => 'Electronics'],
    ['name' => 'Mouse', 'price' => 25, 'category' => 'Electronics'],
    ['name' => 'Book', 'price' => 15, 'category' => 'Education'],
    ['name' => 'Monitor', 'price' => 300, 'category' => 'Electronics']
];

// Sort by price (ascending)
usort($products, function($a, $b) {
    return $a['price'] <=> $b['price'];
});

// Sort by price (descending)
usort($products, fn($a, $b) => $b['price'] <=> $a['price']);

// Multi-level sorting: category first, then price
usort($products, function($a, $b) {
    $categoryCompare = $a['category'] <=> $b['category'];
    if ($categoryCompare === 0) {
        return $a['price'] <=> $b['price'];
    }
    return $categoryCompare;
});

// Sort users by multiple criteria
$users = [
    ['name' => 'John', 'age' => 30, 'department' => 'IT', 'salary' => 75000],
    ['name' => 'Jane', 'age' => 25, 'department' => 'HR', 'salary' => 65000],
    ['name' => 'Bob', 'age' => 35, 'department' => 'IT', 'salary' => 85000],
    ['name' => 'Alice', 'age' => 28, 'department' => 'HR', 'salary' => 70000]
];

// Sort by department, then by salary (descending)
usort($users, function($a, $b) {
    $deptCompare = $a['department'] <=> $b['department'];
    if ($deptCompare === 0) {
        return $b['salary'] <=> $a['salary']; // Higher salary first
    }
    return $deptCompare;
});

// Custom sorting class
class ArraySorter {
    public static function sortByField(array &$array, string $field, bool $ascending = true): void {
        usort($array, function($a, $b) use ($field, $ascending) {
            $valueA = $a[$field] ?? '';
            $valueB = $b[$field] ?? '';
            
            $result = $valueA <=> $valueB;
            return $ascending ? $result : -$result;
        });
    }
    
    public static function sortByMultipleFields(array &$array, array $fields): void {
        usort($array, function($a, $b) use ($fields) {
            foreach ($fields as $field => $direction) {
                $valueA = $a[$field] ?? '';
                $valueB = $b[$field] ?? '';
                
                $result = $valueA <=> $valueB;
                if ($result !== 0) {
                    return $direction === 'desc' ? -$result : $result;
                }
            }
            return 0;
        });
    }
}

// Usage of custom sorter
ArraySorter::sortByField($products, 'name');
ArraySorter::sortByMultipleFields($users, [
    'department' => 'asc',
    'salary' => 'desc',
    'age' => 'asc'
]);

// Sort associative array by values while preserving keys
$rankings = ['Team A' => 245, 'Team B' => 189, 'Team C' => 267, 'Team D' => 203];

// Maintain key associations
uasort($rankings, fn($a, $b) => $b <=> $a); // Descending
// Result: ['Team C' => 267, 'Team A' => 245, 'Team D' => 203, 'Team B' => 189]

// Sort by keys with custom function
$months = [
    'December' => 31,
    'January' => 31,
    'February' => 28,
    'March' => 31
];

uksort($months, function($a, $b) {
    $monthOrder = [
        'January' => 1, 'February' => 2, 'March' => 3,
        'April' => 4, 'May' => 5, 'June' => 6,
        'July' => 7, 'August' => 8, 'September' => 9,
        'October' => 10, 'November' => 11, 'December' => 12
    ];
    
    return $monthOrder[$a] <=> $monthOrder[$b];
});

// Natural sorting for version numbers
$versions = ['v1.10', 'v1.2', 'v1.1', 'v2.0', 'v1.9'];
natsort($versions);
// Result: Correctly ordered versions

// Sort files by modification time
$files = [
    'file1.txt' => filemtime('file1.txt'),
    'file2.txt' => filemtime('file2.txt'),
    'file3.txt' => filemtime('file3.txt')
];

// Sort by newest first
arsort($files);

// Complex sorting with date objects
$events = [
    ['name' => 'Meeting', 'date' => new DateTime('2024-03-15')],
    ['name' => 'Conference', 'date' => new DateTime('2024-02-20')],
    ['name' => 'Workshop', 'date' => new DateTime('2024-04-10')]
];

usort($events, function($a, $b) {
    return $a['date'] <=> $b['date'];
});

// Stable sorting (maintains relative order for equal elements)
function stableSort(array &$array, callable $compare): void {
    $indexed = [];
    foreach ($array as $index => $item) {
        $indexed[] = [$item, $index];
    }
    
    usort($indexed, function($a, $b) use ($compare) {
        $result = $compare($a[0], $b[0]);
        return $result === 0 ? $a[1] <=> $b[1] : $result;
    });
    
    $array = array_column($indexed, 0);
}

// Performance comparison for large arrays
function benchmarkSorting(array $data): array {
    $results = [];
    
    // Test different sorting methods
    $methods = [
        'sort' => function($arr) { sort($arr); return $arr; },
        'asort' => function($arr) { asort($arr); return $arr; },
        'usort' => function($arr) { 
            usort($arr, fn($a, $b) => $a <=> $b); 
            return $arr; 
        }
    ];
    
    foreach ($methods as $name => $method) {
        $testData = $data;
        $start = microtime(true);
        $method($testData);
        $results[$name] = microtime(true) - $start;
    }
    
    return $results;
}

// Sort with null handling
function sortWithNulls(array &$array, string $field, bool $nullsFirst = true): void {
    usort($array, function($a, $b) use ($field, $nullsFirst) {
        $valueA = $a[$field] ?? null;
        $valueB = $b[$field] ?? null;
        
        if ($valueA === null && $valueB === null) return 0;
        if ($valueA === null) return $nullsFirst ? -1 : 1;
        if ($valueB === null) return $nullsFirst ? 1 : -1;
        
        return $valueA <=> $valueB;
    });
}

// Locale-aware sorting
$names = ['Müller', 'Smith', 'Åberg', 'Zhang'];
if (class_exists('Collator')) {
    $collator = new Collator('en_US');
    $collator->sort($names);
}

// Sort by calculated values
$items = [
    ['length' => 10, 'width' => 5],
    ['length' => 8, 'width' => 7],
    ['length' => 12, 'width' => 4]
];

// Sort by area (length × width)
usort($items, function($a, $b) {
    $areaA = $a['length'] * $a['width'];
    $areaB = $b['length'] * $b['width'];
    return $areaA <=> $areaB;
});

// Usage examples with output
echo "Sorted products by price:\n";
foreach ($products as $product) {
    echo "- {$product['name']}: \${$product['price']}\n";
}

echo "\nSorted users by department and salary:\n";
foreach ($users as $user) {
    echo "- {$user['name']} ({$user['department']}): \${$user['salary']}\n";
}

echo "\nTop teams by ranking:\n";
foreach ($rankings as $team => $score) {
    echo "- $team: $score points\n";
}

echo "\nMonths in chronological order:\n";
foreach ($months as $month => $days) {
    echo "- $month: $days days\n";
}

Behind the Scenes

PHP provides different sorting functions for specific needs: sort() for simple value sorting with key renumbering, asort() for value sorting with key preservation, ksort() for key sorting, and usort() family for custom comparison logic using the spaceship operator.

The spaceship operator (<=>) returns -1, 0, or 1 for less than, equal to, or greater than comparisons, making it perfect for sorting callbacks. For complex sorting, combine multiple comparisons and use early returns to handle null values appropriately.

Critical for data presentation, search results, leaderboards, and any application requiring organized data display. Always consider whether you need to preserve key associations and choose the appropriate sorting function for your use case.

Share this article

Add Comment

No comments yet. Be the first to comment!

More from Php