usort多字段排序

46

是否可以使用usort对多维数组中的多个字段进行排序?例如,我想按字母顺序排序name,然后从这些记录中按age进行排序。这是否可以使用sort实现?

Array ( 
    [0] => Array ( 
        [name] => Jonah 
        [age] => 27 
    )
    [1] => Array (
        [name] => Bianca 
        [age] => 32 
    )
)

可能是重复的问题:按多个键对多维数组进行排序 - salathe
3个回答

92

你可以试试这个:

$arr = Array (
    0 => Array (
        'name' => 'Jonah',
        'age' => '27',
    ),
    1 => Array (
        'name' => 'Bianca',
        'age' => '32',
    ),
    2 => Array (
        'name' => 'Jonah',
        'age' => '25',
    ),
    3 => Array (
        'name' => 'Bianca',
        'age' => '35',
    ),
);
function comp($a, $b) {
    if ($a['name'] == $b['name']) {
        return $a['age'] - $b['age'];
    }
    return strcmp($a['name'], $b['name']);
}

usort($arr, 'comp');
print_r($arr);

输出:

Array
(
    [0] => Array
        (
            [name] => Bianca
            [age] => 32
        )

    [1] => Array
        (
            [name] => Bianca
            [age] => 35
        )

    [2] => Array
        (
            [name] => Jonah
            [age] => 25
        )

    [3] => Array
        (
            [name] => Jonah
            [age] => 27
        )

)

嗨,如果想要降序排列年龄,是不是应该写成 return $a['age'] + $b['age']; - Swee Hong
@SweeHong:使用以下代码:return $b['age'] - $a['age']; - Toto
如果年龄是一个字符串,你可以使用strcmp($a['age'], $b['age'])函数。 - somtam
4
从PHP 7开始,您可以使用以下单行代码编写比较函数: return $a['name'] <=> $b['name'] ?: $a['age'] <=> $b['age'];解释在这里:https://wiki.php.net/rfc/combined-comparison-operator - Gogowitsch

42
usort($arr, function($a, $b)
{
    $name = strcmp($a['name'], $b['name']);
    if($name === 0)
    {
        return $a['age'] - $b['age'];
    }
    return $name;
});

出于好奇,如果我要对“名称”进行排序,但它是一个整数而不是字符串(例如),你会推荐使用哪个函数,而不是使用“strcmp”? - user1205775
@user1205775:只使用简单的算术运算符就可以很好地解决问题。 - user142162

19
怎么样:
<?php

function getRandomName() {
    $possible = "ab";
    $possible_len = strlen($possible);
    $r = '';
    for ($i = 0; $i < 4; $i++) {
        $r .=  substr($possible, mt_rand(0, $possible_len-1), 1);
    }
    return ucfirst($r);
}

$a = array();
for ($i = 0; $i < 10; $i++) {
    $a[] = array('name' => getRandomName(), 'age' => rand(1,10), 'start_order' => $i);
}
$order = array('name' => 'desc', 'age' => 'asc');

print_r($a);

usort($a, function ($a, $b) use ($order) {
    $t = array(true => -1, false => 1);
    $r = true;
    $k = 1;
    foreach ($order as $key => $value) {
        $k = ($value === 'asc') ? 1 : -1;
        $r = ($a[$key] < $b[$key]);
        if ($a[$key] !== $b[$key]) {
            return $t[$r] * $k;
        }

    }
    return $t[$r] * $k;
});

print_r($a);

4
我找过多种研究后发现,这个解决方案是最好的!它可以独立地处理你想要排序的参数数量,并且可以按升序或降序排列。 - GRosay
1
这绝对是最好的、最多才多艺的解决方案! - Dominique

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接