簡體   English   中英

PHP 如何使用字母順序備份基於優先級順序對對象數組進行排序?

[英]PHP How to sort an array of objects based on priority order with a backup of alphabetical?

我有一個這樣的數組:

$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中的任何內容不匹配的其他元素應按字母順序排列在數組的末尾。

In javascript I would use call a sort function with a comparator function that takes 2 elements and returns a number to place the first object ahead or behind the second.

如何使用 PHP 做到這一點?

編輯

我嘗試了一些東西,但沒有成功。 (再次修改,將邏輯放到一個function中,並概括按哪個字段排序)

<?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

預期的 output 是

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

我不知道如何compare function 以正確使用特定於上下文的$sort_order function。

編輯

我接受了一個答案,但為了完整起見,我想發布我最終得到的似乎可行的內容。 如果有人想發布更優雅的解決方案,我會考慮將其標記為已接受。 但這是我所擁有的:

<?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);
?>

您可以像使用 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();
?>

對於具有較少函數調用的最干凈的腳本,請將usort()與 spaceship 運算符一起使用。

我遵循的技術遵循兩步邏輯(包含條件的第一步):

  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"];

處理代碼:(演示

$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']]
);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM