对2-D关联数组进行排序并根据键值进行分类

时间:2013-04-23 01:55:02

标签: php

我是新手。有一个关于PHP排序的问题。已经搜索了很多,但遗憾的是找不到我正在搜索的解决方案。我知道这很容易 - 但我不知道为什么在搜索几个小时之后我找不到它。

我有一个像这样的数组。他们有一个关键的“职责”,我想对此做一些排序,以便新数组包含 - 数组与“职责”字段一致。

$arrayName = array(
array(
    'name' => 'Dr. Hugo Lopez',
    'duty' => 'Anesthesiologist',
    'link' => ''
),
array(
    'name' => 'Dr. Dario Garin',
    'duty' => 'Orthopedic Specialist',
    'link' => 'dr-dario-garin.php'
),
array(
    'name' => 'Dr. Maclovio Yañez',
    'duty' => 'Plastic Surgeon',
    'link' => ''
),
array(
    'name' => 'Melissa Bracker',
    'duty' => 'Patient Liaison',
    'link' => ''
),
array(
    'name' => 'Dr. Diego Guzman',
    'duty' => 'Cardiologist',
    'link' => ''
),
array(
    'name' => 'Ivan Arafat',
    'duty' => 'Accountant',
    'link' => ''
),
array(
    'img-old' => 'jorge-fernandez.jpg',
    'duty' => 'Hospital Administrator',
    'link' => ''
),
);

我试过了:

usort($arrayName, function($a, $b) {
return $a['duty'] - $b['duty'];
});

但是这会按照Duty字段的降序排列数组。

我想按照Duty字段优先顺序排列。 例如:我将设置Duty字段值的顺序,以按护士,维护,医生,司机等类别排列。

我希望能够 - 使用某种数组自己设置分类顺序。

sort($arrayName, $priority);
$priority = array( 'President', 'Vice President', 'Doctors', 'Nurse', 'Maintenance', 'Drivers');

我对PHP并不熟悉。如果我在问基本问题,请原谅。

4 个答案:

答案 0 :(得分:0)

usort($arrayName, function (array $a, array $b) {
    static $priority = array('President', 'Vice President', 'Doctors', 'Nurse', 'Maintenance', 'Drivers');
    return array_search($a['duty'], $priority) - array_search($b['duty'], $priority);
});

答案 1 :(得分:0)

老实说,我会改变你组织数据结构的方式 - 有许多轻微的低效率可能会伤害你。您的专业人员列表属于某个部门而不是具有描述其角色的属性更为自然。如果将用户分组为以下数据结构,则执行排序和其他“部门”级别任务变得更加容易,而不会使“用户”级别任务变得更加困难。

$arry = array(
   'Accountant' => array(
        ...
    ),
    'Anesthesiologist' => array(
        ...
    ),
)

如果这不是一个选项..您可以使用下面的功能..但请注意,我不建议在任何生产场景中以这种方式对数据进行排序。它为您设置的每个优先级迭代整个用户列表,这是一种非常低效的排序方法。想象一下,您有100个优先级和1000个用户的情况 - 这将需要100 * 1000 = 100,000次迭代才能简单地确定数据的优先级。最糟糕的是它会以指数方式变慢。

无论如何,这是效率低下的解决方案..

$priorities = array(
        'Accountant',
        'Cardiologist',
        'Anesthesiologist',
);

$arrayName = array(
...
);

$r = sortDuties($arrayName, $priorities);
var_dump($r);

function sortDuties($userList, $priorities = array()) {
 $newList = array();
 foreach($priorities AS $priority) {
    for($i = 0; $i < count($userList); $i++) {
        if(isset($userList[$i]) && $userList[$i]['duty'] == $priority){
            $newList[] = $userList[$i];
            unset($userList[$i]);
        }
    }
 }

 return array_merge($newList, $userList);
}

答案 2 :(得分:0)

这是我的解决方案,不是最有效的,但应该做到这一点,它应该解决未定义为优先权的责任问题。

$priority = array('Orthopedic Specialist', 'Hospital Administrator', 'Accountant', 'Anesthesiologist', 'Plastic Surgeon');

function dutySort(array &$array, array $priority) {

    usort($array, function($a, $b) use ($priority) {
        $aPriority = array_search($a['duty'], $priority);
        $aPriority = ($aPriority !== false ? $aPriority : count($priority));
        $bPriority = array_search($b['duty'], $priority);
        $bPriority = ($bPriority !== false ? $bPriority : count($priority));

        return ($aPriority < $bPriority) ? -1 : 1;
    });
}

dutySort($array, $priority);

答案 3 :(得分:0)

由于isset()(或我将演示的空合并)始终胜过array_search(),因此建议您通过翻转优先级数组来准备查找数组。当职责不在优先级数组中时,您将需要分配一个高于最高优先级值的数字-为此,只需使用count()

代码:(Demo

$array = [
    ['name' => 'Dr. Hugo Lopez', 'duty' => 'Anesthesiologist', 'link' => ''],
    ['name' => 'Dr. Dario Garin', 'duty' => 'Orthopedic Specialist', 'link' => 'dr-dario-garin.php'],
    ['name' => 'Dr. Maclovio Yañez', 'duty' => 'Plastic Surgeon', 'link' => ''],
    ['name' => 'Melissa Bracker', 'duty' => 'Patient Liaison', 'link' => ''],
    ['name' => 'Dr. Diego Guzman', 'duty' => 'Cardiologist', 'link' => ''],
    ['name' => 'Ivan Arafat', 'duty' => 'Accountant', 'link' => ''],
    ['name' => 'Jorge Fernandez', 'duty' => 'Hospital Administrator', 'link' => ''],
];

$lookup = array_flip(['Hospital Administrator', 'Plastic Surgeon', 'Orthopedic Specialist']);
$fallback = count($lookup);

usort($array, function ($a, $b) use ($lookup, $fallback) {
    return ($lookup[$a['duty']] ?? $fallback) <=> ($lookup[$b['duty']] ?? $fallback);
});
var_export($array);

如果要扩展基于name的排序规则,则太空飞船操作员将使其变得非常简单。事实是,名称字符串的解析比排序困难。我将名称分成最多3个元素,然后颠倒它们的顺序,以使它们成为“姓氏”,“名字”,“前缀”。

代码:(Demo

usort($array, function ($a, $b) use ($lookup, $fallback) {
    $aName = array_reverse(preg_match('~^((?:[a-z]+\.)?) ?(\S+) (.+)~i', $a['name'], $out) ? $out : ['', '', '']);
    $bName = array_reverse(preg_match('~^((?:[a-z]+\.)?) ?(\S+) (.+)~i', $b['name'], $out) ? $out : ['', '', '']);
    return [$lookup[$a['duty']] ?? $fallback, ...$aName]
           <=>
           [$lookup[$b['duty']] ?? $fallback, ...$bName];
});