按自定义条件对数组进行排序


sort array by custom criteria

我有一个对象数组:

object1->
name="Name1"
key="key1"
object2->
name="Name2"
key="key2"
object3->
name="Name3"
key="key3"

和一系列优先级键:

$keys = ["key3", "key1"];

我需要根据优先级键对对象数组进行排序,因此结果应该是:

object3:
name="Name3"
key="key3"
object1->
name="Name1"
key="key1"
object2:
name="Name2"
key="key2"

最好的方法是什么?

这个想法是将优先级添加为整数,并使用usort()将数组从最高整数排序到最低

整数

例如,您有此数据

 <?php
 $data = [];
 $data[0] = new stdClass;
 $data[0]->name = "name1";
 $data[0]->key = 'key1';
 $data[1] = new stdClass;
 $data[1]->name = "name2";
 $data[1]->key = 'key2';
 $data[2] = new stdClass;
 $data[2]->name = "name3";
 $data[2]->key = 'key3';

 $keys = ["key3", "key1"];

您可以按这种方式排序

function sortByPriority($data , $keys){
    $priority = array();
    $i = count($keys);
    foreach ($keys as $key => $value) {
      $i--;
      $priority[$value] = $i;
    }
    usort($data, function($a, $b) use($priority){
      $a = isset($priority[$a->key]) ? $priority[$a->key] : -1;
      $b = isset($priority[$b->key]) ? $priority[$b->key] : -1;
      return $b - $a;
    });
    return $data;
 }

 var_dump(sortByPriority($data, $keys));    

示例输出

array (size=3)
  0 => 
    object(stdClass)[3]
      public 'name' => string 'name3' (length=5)
      public 'key' => string 'key3' (length=4)
  1 => 
    object(stdClass)[1]
      public 'name' => string 'name1' (length=5)
      public 'key' => string 'key1' (length=4)
  2 => 
    object(stdClass)[2]
      public 'name' => string 'name2' (length=5)
      public 'key' => string 'key2' (length=4)    

一旦你准备好了优先级查找数组,只需将其传递到usort()的作用域,然后使用相关的优先级值,或者如果key属性的值不在优先级数组中,则使用回退值。 可读、直接、简洁。

代码:(演示)

$objects = [
   (object)["name" => "Name1", "key" => "key1"],
   (object)["name" => "Name2", "key" => "key2"],
   (object)["name" => "Name3", "key" => "key3"],
];
$keys = ["key3", "key1"];
$lookup = array_flip($keys);
$fallback = count($keys);
usort($objects, function($a, $b) use ($lookup, $fallback) {
    return ($lookup[$a->key] ?? $fallback) <=> ($lookup[$b->key] ?? $fallback);
});
var_export($objects);

输出:

array (
  0 => 
  (object) array(
     'name' => 'Name3',
     'key' => 'key3',
  ),
  1 => 
  (object) array(
     'name' => 'Name1',
     'key' => 'key1',
  ),
  2 => 
  (object) array(
     'name' => 'Name2',
     'key' => 'key2',
  ),
)
<小时 />

从 PHP7.4 开始,语法可以进一步压缩,use()声明可以省略。(演示)

usort($objects, fn($a, $b) => ($lookup[$a->key] ?? $fallback) <=> ($lookup[$b->key] ?? $fallback));

PHP 中有函数 usort 做你需要的:

usort( $your_array), "sort_function");
sort_function( $a, $b) {
   // your sort logic
}