尝试在 php 中使用 usort 对对象数组进行排序
Trying to sort an array of objects using usort in php
我正在 WordPress 网站上工作,试图对 post 标签进行排序,这是一个包含各种成员的对象数组,包括 slug
和 name
。我已经按优先顺序创建了一个标签 slug 字符串数组,并尝试根据该数组的值对 post 的标签数组进行排序,并以 post 的 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->slug
是一个类似于“strategy”的字符串,但它也表明 $tagPriorityMap[$a->slug]
returns没有价值。我究竟做错了什么?谢谢。
你的$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;
}
我真的很奇怪为什么@Cârnăciov 删除了他的答案,它比被接受的答案要好得多。
将优先级转储到全局中对于测试来说是可以的,但是如果您通过乱用全局名称空间来解决所有问题,您很快就会遇到麻烦。
您可以像 Cârnaciov 建议的那样使用 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
我正在 WordPress 网站上工作,试图对 post 标签进行排序,这是一个包含各种成员的对象数组,包括 slug
和 name
。我已经按优先顺序创建了一个标签 slug 字符串数组,并尝试根据该数组的值对 post 的标签数组进行排序,并以 post 的 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->slug
是一个类似于“strategy”的字符串,但它也表明 $tagPriorityMap[$a->slug]
returns没有价值。我究竟做错了什么?谢谢。
你的$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;
}
我真的很奇怪为什么@Cârnăciov 删除了他的答案,它比被接受的答案要好得多。
将优先级转储到全局中对于测试来说是可以的,但是如果您通过乱用全局名称空间来解决所有问题,您很快就会遇到麻烦。
您可以像 Cârnaciov 建议的那样使用 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