【问题标题】:Trying to sort an array of objects using usort in php尝试在 php 中使用 usort 对对象数组进行排序
【发布时间】:2023-05-22 04:51:02
【问题描述】:

我正在开发一个 WordPress 网站,尝试对帖子标签进行排序,这是一个包含 slugname 在内的各种成员的对象数组。我已经按优先级顺序创建了一个标签 slug 字符串数组,并尝试根据该数组的值对帖子的标签数组进行排序,并以帖子的 slug 作为键。示例:

$tagPriorityMap = array(
  "research" => 0,
  "strategy" => 1,
  "naming" => 2,
  "identity" => 3,
  "packaging" => 4,
  "environment" => 5,
  "digital" => 6,
);
function sort_tags($a, $b) {
  if ($tagPriorityMap[$a->slug] == $tagPriorityMap[$b->slug]) {
    return 0;
  }
  return ($tagPriorityMap[$a->slug] < $tagPriorityMap[$b->slug]) ? -1 : 1;
}

如果我在 sort_tags 函数中回显一些代码,它表明 $a-&gt;slug 是一个类似于“策略”的字符串,但它也表明 $tagPriorityMap[$a-&gt;slug] 没有返回值。我究竟做错了什么?谢谢。

【问题讨论】:

  • 除了如答案所示使该变量成为全局变量外,您还可以将其移动到函数内部。

标签: php usort


【解决方案1】:

您的$tagPriorityMap 必须在函数内声明为全局变量。 试试看:

function sort_tags($a, $b) {
  global $tagPriorityMap;
  if ($tagPriorityMap[$a->slug] == $tagPriorityMap[$b->slug]) {
    return 0;
  }
  return ($tagPriorityMap[$a->slug] < $tagPriorityMap[$b->slug]) ? -1 : 1;
}

已添加 想法来自Maik Lowrey

只需添加$tagPriorityMap 作为函数的参数即可全局使用

function sort_tags($a, $b, $tagPriorityMap) {
  if ($tagPriorityMap[$a->slug] == $tagPriorityMap[$b->slug]) {
    return 0;
  }
  return ($tagPriorityMap[$a->slug] < $tagPriorityMap[$b->slug]) ? -1 : 1;
}

【讨论】:

  • 或者将$tagPriorityMap传递给函数sort_tags($a, $b, $tagPriorityMap)。
  • 在我看来,定义一个全局并不是最好的解决方案......
【解决方案2】:

我真的很想知道为什么@Cârnăciov 删除了他的答案,它比被接受的要好得多。
将优先级转储到全局中对于测试来说是可以的,但是如果您通过乱扔全局命名空间来解决所有问题,那么您很快就会遇到麻烦。

您可以像 Cârnăciov 建议的那样使用 use() 关键字来避免这种情况。

但您可以直接在函数内部将优先级定义为静态变量。它的行为与全局完全一样,除了比较函数之外没有人会看到它。
PHP7 spaceship operator 也可以用来简化比较,它是为此量身定做的:

function sort_tags ($a, $b) {
        static $prio = array(
          "research" => 0,
          "strategy" => 1,
          "naming" => 2,
          "identity" => 3,
          "packaging" => 4,
          "environment" => 5,
          "digital" => 6,
        );
        return $prio[$a->slug] <=> $prio[$b->slug];
    }

或者你也可以使用arrow functions。这些允许您模拟过去 25 年来 JavaScript 处理闭包的复杂方式:D
(抱歉,开个小玩笑)

$sort_tags = (function () { // this anonymous function closes over "prio"
        $prio = array(      // and returns the actual comparison function
          "research" => 0,
          "strategy" => 1,
          "naming" => 2,
          "identity" => 3,
          "packaging" => 4,
          "environment" => 5,
          "digital" => 6,
        );
        // the comparison function sees "prio" captured in the upper level closure
        return fn ($a, $b) => 
            $prio[$a->slug] <=> $prio[$b->slug]; // handles the -1, 0 and 1 cases in one go
    })(); // immediately invoked function expression, just like in JavaScript

一个愚蠢的例子表明你不再需要一个全局变量:

文件test.php

<?php

function demo () {
    
    $sort_tags = function ($a, $b) {
            static $prio = array(
              "research" => 0,
              "strategy" => 1,
              "naming" => 2,
              "identity" => 3,
              "packaging" => 4,
              "environment" => 5,
              "digital" => 6,
            );
            return $prio[$a->slug] <=> $prio[$b->slug];
    };


    $sample = [
        (object)["slug" => "naming"   , "id" => 1],
        (object)["slug" => "packaging", "id" => 2],
        (object)["slug" => "research" , "id" => 3],
        (object)["slug" => "strategy" , "id" => 4]];

    echo "<br>before usort:<br><br>";
    foreach ($sample as $item) echo $item->slug, " => ", $item->id, "<br>";
    echo "<br>after usort:<br><br>";

    usort ($sample, $sort_tags);

    foreach ($sample as $item) echo $item->slug, " => ", $item->id, "<br>";
}

demo();
?>

浏览器输出

before usort:

naming => 1
packaging => 2
research => 3
strategy => 4

after usort:

research => 3
strategy => 4
naming => 1
packaging => 2

【讨论】:

    最近更新 更多