按自定义排序优先级(非字母表顺序)对数组的数组进行排序

5

假设我有这个数组:

$array = array(
    array("id" => 7867867, "animal" => "Dog"),
    array("id" => 3452342, "animal" => "Lion"),
    array("id" => 1231233, "animal" => "Lion"),
    array("id" => 5867867, "animal" => "Dog"),
    array("id" => 1111111, "animal" => "Zeebra"),
    array("id" => 2222222, "animal" => "Cat"),
    array("id" => 3333333, "animal" => "Cat"),
    array("id" => 4444444, "animal" => "Zeebra")
);

我尝试使用PHP排序函数按照指定规则对内容进行排序(不是按字母顺序)。

客户要求将信息按“狮子第一,狗第二,斑马第三,猫第四”进行排序。

类似于以下内容:

$array = array(
    array("id" => 3452342, "animal" => "Lion"),
    array("id" => 1231233, "animal" => "Lion"),
    array("id" => 7867867, "animal" => "Dog"),
    array("id" => 5867867, "animal" => "Dog"),
    array("id" => 4444444, "animal" => "Zeebra"),
    array("id" => 1111111, "animal" => "Zeebra"),
    array("id" => 2222222, "animal" => "Cat"),
    array("id" => 3333333, "animal" => "Cat"),
);

该数组将使用"animal"值进行排序,并基于预定的规则。

我试图弄清楚php排序函数,但我只能让它们按字母或数字排序。

我已经成功使用一块if语句和循环,但我想尽快摆脱这个缓慢的代码。

5个回答

7
使用Jonathan建议中提到的usort函数,您可以在一个单独的函数中定义自己的排序规则,例如:
使用usort函数,您可以在一个单独的函数中定义自己的排序规则,例如:
function getAnimalValue($animal) {
    switch($animal) {
        case 'Lion':
            return 1;
        case 'Dog':
            return 2;
        case 'Zeebra':
            return 3;
        case 'Cat':
            return 4;
    }
    return 0;
}

然后,实现您自己的比较函数:

function compare($itemA, $itemB) {
    $a = getAnimalValue($itemA['animal']);
    $b = getAnimalValue($itemB['animal']);
    if ($a == $b) {
        return 0;
    }
    return ($a < $b) ? -1 : 1;
}

最后,使用比较函数调用usort:
usort($array, "compare");

3

PHP7提供了"太空船操作符",使排序变得更加简单。

以下所有代码片段都将利用查找数组来确定自定义排序顺序。

$priorities = array_flip(['Lion', 'Dog', 'Zeebra', 'Cat']);

代码: (演示)

usort($array, function($a, $b) use ($priorities) {
    return $priorities[$a['animal']] <=> $priorities[$b['animal']];
});

PHP7.4+ 代码:(演示

usort($array, fn($a, $b) => $priorities[$a['animal']] <=> $priorities[$b['animal']]);

你的问题和示例数据表明,你的查找数组中始终包含所有动物。如果不总是这样,那么你需要在自定义函数中进行 isset() 调用,并确定是否要将缺失的动物放在列表的前面或后面。
上述两个代码段都提供了相同的输出:
array (
  0 => 
  array (
    'id' => 3452342,
    'animal' => 'Lion',
  ),
  1 => 
  array (
    'id' => 1231233,
    'animal' => 'Lion',
  ),
  2 => 
  array (
    'id' => 7867867,
    'animal' => 'Dog',
  ),
  3 => 
  array (
    'id' => 5867867,
    'animal' => 'Dog',
  ),
  4 => 
  array (
    'id' => 1111111,
    'animal' => 'Zeebra',
  ),
  5 => 
  array (
    'id' => 4444444,
    'animal' => 'Zeebra',
  ),
  6 => 
  array (
    'id' => 2222222,
    'animal' => 'Cat',
  ),
  7 => 
  array (
    'id' => 3333333,
    'animal' => 'Cat',
  ),
)

2

查看 usort。这里是参考链接:

http://www.php.net/manual/en/function.usort.php

示例:

function cmp($a, $b) {
    $order=array("Lion","Dog","Zebra","Cat");
    if ($a["animal"] == $b["animal"]) {
        return 0;
    }
    return (array_search($a["animal"],$order) < array_search($b["animal"],$order)) ? -1 : 1;
}

$array = array(
    array("id" => 7867867, "animal" => "Dog"),
    array("id" => 3452342, "animal" => "Lion"),
    array("id" => 1231233, "animal" => "Lion"),
    array("id" => 5867867, "animal" => "Dog"),
    array("id" => 1111111, "animal" => "Zebra"),
    array("id" => 2222222, "animal" => "Cat"),
    array("id" => 3333333, "animal" => "Cat"),
    array("id" => 4444444, "animal" => "Zebra")
);

$mySortedArray=usort($array, "cmp");

你能举个例子说明我如何使用它来将字符串值与用户定义的规则进行比较吗? - Nick S.
这是一个很好的例子,但现在你可以使用太空船操作符<=>来使代码更简单。usort($animals, function ($a, $b) { $order = ['Dog', 'Lion', 'Zeebra', 'Cat']; return (array_search($a["animal"],$order) <=> array_search($b["animal"],$order)); }); - MrsPop88
1
@JasonBruce,是的,这个答案是在PHP添加太空船运算符之前提供的。随时更新答案。 - Jonathan M

0

这是有点丑陋的方式,但它可以工作。

// Set our rules, the key is the order
$rules = array(0=>"Dog",1=>"Lion",2=>"Zeebra",3=>"Cat");

// Our array
$array = array(
    array("id" => 7867867, "animal" => "Dog"),
    array("id" => 3452342, "animal" => "Lion"),
    array("id" => 1231233, "animal" => "Lion"),
    array("id" => 5867867, "animal" => "Dog"),
    array("id" => 1111111, "animal" => "Zeebra"),
    array("id" => 2222222, "animal" => "Cat"),
    array("id" => 3333333, "animal" => "Cat"),
    array("id" => 4444444, "animal" => "Zeebra")
);

// Split each animal into a arrays per animal
foreach( $array as $item ){
    $animals[ $item['animal'] ][] = $item;
}

// Loop our rules (dogs, then lions, etc) and put our mini arrays in a final sorted_array.
foreach( $rules as $animal_order => $animal_name ){
    foreach( $animals[$animal_name] as $animal ){
        $sorted_animals[] = $animal;
    }

}

print_r($sorted_animals);

-1

尝试:

function sortByAnimals($array, $animalOrderArray){
  foreach($animalOrderArray as $v){
    $aa[$v] = array();
  }
  foreach($array as $a){
    foreach($aa as $i => $v){
      if(preg_match("/^{$a['animal']}$/i", $i)){
        array_push($aa[$i], $a);
        break;
      }
    }
  }
  foreach($aa as $a){
    foreach($a as $v){
      $r[] = $v;
    }
  }
  return $r;
}
$resArray = sortByAnimals($array, array('lion', 'dog', 'zeebra', 'cat'));

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