PHP如何使用字母顺序备份基于优先级顺序对对象数组进行排序?

时间:2014-01-11 21:22:07

标签: php arrays sorting

我有一个这样的数组:

$sort_me = array(
   array("file"=>"Desert.jpg"), 
   array("file"=>"Hello.jpg"), 
   array("file"=>"Test.jpg)
)

我想按字母顺序基于文件属性对此数组进行排序。更复杂的是我有一个可选的数组:

$sort_order = array("Test.jpg", "Hello.jpg", "NotFound.jpg")

此数组将指定一些用户定义的排序。这些数组元素具有优先级,如果找到它们将按此顺序放置。其他与$sort_order中的任何内容不匹配的元素应按字母顺序排列在数组的末尾。

在javascript中我会使用一个带有比较器函数的sort函数,它接受2个元素并返回一个数字,将第一个对象放在第二个对象的前面或后面。

如何使用PHP执行此操作?

修改

我尝试了一些东西而且没用。 (再次修改以将逻辑放入一个函数,并概括要排序的字段)

<?php
    function sort_priority($sort_me, $sort_order, $field) {
        function compare($a, $b) {
            if ($sort_order) {
                $ai = array_search($a[$field], $sort_order);
                $bi = array_search($b[$field], $sort_order);
                if ($ai !== false && $bi === false) {
                    return -1;
                } else if ($bi !== false && $ai === false) {
                    return 1;
                } else if ($ai !== false && $bi !== false) {
                    return $bi - $ai;
                }
            }
            return $a[$field] < $b[$field] ? -1 : 1;
        }
        usort($sort_me, "compare");
    }

    $sort_order = array("Test.jpg", "Hello.jpg", "NotFound.jpg");
    $sort_me = array(
       array("file"=>"Test.jpg"),
       array("file"=>"Desert.jpg"),
       array("file"=>"Hello.jpg")
    );

    sort_priority($sort_me, $sort_order, "file");
    echo json_encode($sort_me);
?>

此输出

 Notice: Undefined variable: sort_order in c:\workspace\test.php on line 10

预期输出

[{"file":"Test.jpg"},{"file":"Hello.jpg"},{"file":"Desert.jpg"}]

我不知道如何让compare函数正确使用特定于上下文的$sort_order函数。

修改

我接受了一个答案,但为了完整起见,我想发布我最终结束的内容似乎有效。如果有人想发布更优雅的解决方案,我会考虑将其标记为已接受。但这就是我所拥有的:

<?php
    function compare_priority($a, $b) {
        global $g_order, $g_field;
        if ($g_order) {
            $ai = array_search($a[$g_field], $g_order);
            $bi = array_search($b[$g_field], $g_order);
            if ($ai !== false && $bi === false) {
                return -1;
            } else if ($bi !== false && $ai === false) {
                return 1;
            } else if ($ai !== false && $bi !== false) {
                return $ai - $bi;
            }
        }
        return $a[$g_field] < $b[$g_field] ? -1 : 1;
    }

    function sort_priority(&$sort_me, $sort_order, $field) {
        global $g_order, $g_field;
        $g_order = $sort_order;
        $g_field = $field;
        usort($sort_me, "compare_priority");
    }

    $sort_me = array(
       array("file"=>"Z"), 
       array("file"=>"A"), 
       array("file"=>"Y"), 
       array("file"=>"B")
    );
    $sort_order = array("Z", "Y", "C");
    sort_priority($sort_me, $sort_order, "file");
    echo json_encode($sort_me);
?>

2 个答案:

答案 0 :(得分:1)

你可以像使用javascript一样做。 usort(http://ch2.php.net/manual/en/function.usort.php)允许您定义元素之间的自定义比较。

我修改了你的代码,似乎有效:

<?php
    function test() {
        $sort_me = array(
           array("file"=>"Test.jpg"),
           array("file"=>"Desert.jpg"),
           array("file"=>"Hello.jpg")
        );
        global $sort_order;
        $sort_order = array("Test.jpg" , "Hello.jpg", "NotFound.jpg");
        function compare($a, $b) {
            global $sort_order;
            if (is_array($sort_order)) {
                $ai = array_search($a["file"], $sort_order);
                $bi = array_search($b["file"], $sort_order);
                if ($ai !== false && $bi === false) {
                    return -1;
                } else if ($bi !== false && $ai === false) {
                    return 1;
                } else if ($ai !== false && $bi !== false) {
                    return $ai - $bi;
                }
            }
            return $a["file"] < $b["file"] ? -1 : 1;
        }
        usort($sort_me, "compare");
        echo json_encode($sort_me);
    }

    test();
?>

答案 1 :(得分:0)

要使用更少的函数调用来获得最简洁的脚本,请将usort()与飞船运算符配合使用。

我遵循的技术遵循两步逻辑(包含条件的第一步):

  1. 按优先级数组的索引值排序;如果该值不在优先级数组中,则使用后备值(该值高于最后一个元素的键)。
  2. 当打破第一个规则产生的联系时,请按字母顺序排序

样本输入:

$sort_me = [
   ["file" => "Desert.jpg"], 
   ["file" => "What.jpg"], 
   ["file" => "Hello.jpg"], 
   ["file" => "Test.jpg"],
   ["file" => "Goodness.jpg"],
];

$sort_order = ["Test.jpg", "Hello.jpg", "NotFound.jpg"];

处理代码:(Demo

$lookup = array_flip($sort_order);
$fallback = count($sort_order);

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

输出:

array (
  0 => 
  array (
    'file' => 'Test.jpg',
  ),
  1 => 
  array (
    'file' => 'Hello.jpg',
  ),
  2 => 
  array (
    'file' => 'Desert.jpg',
  ),
  3 => 
  array (
    'file' => 'Goodness.jpg',
  ),
  4 => 
  array (
    'file' => 'What.jpg',
  ),
)

从PHP7.4开始,您可以使用箭头函数语法将全局变量引入自定义函数的作用域,而无需使用use()声明。

usort($sort_me, fn($a, $b) =>
    [$lookup[$a['file']] ?? $fallback, $a['file']]
    <=>
    [$lookup[$b['file']] ?? $fallback, $b['file']]
);