php - 按权重值对多维数组进行排序

标签 php arrays sorting usort

这里有很多问题询问如何在 PHP 中对多维数组进行排序。答案是 usort()。我知道。但我有一个问题更进一步,我在这里看不到类似的答案。

我有一系列记录,每条记录都包含一个国家 ID(如果您愿意,也可以是国家名称;这无关紧要)。

我的任务是以有利于特定国家的方式对数组进行排序。这是动态的——即选择喜欢的国家取决于用户的配置。我有一个单独的数组,它指定了前几个国家所需的排序顺序;来自其他国家/地区的结果将在列表末尾未排序。

所以问题是:如何在不使用全局变量的情况下将此排序标准放入 usort() 中。并且最好不要将条件数组注入(inject)主数组的每个元素('因为如果我无论如何都要循环它,那么使用 usort() 有什么意义呢?)

请注意:因为它会与这里的答案相关,所以我暂时停留在 PHP 5.2 上,所以我不能使用匿名函数。我们正在进行升级,但现在我需要适用于 5.2 的答案。 (5.3/5.4 的答案也将受到欢迎,特别是如果它们使它变得更容易,但我将无法使用它们)

最佳答案

你明确地写道你不想拥有全局变量,所以我也不建议你使用静态变量,因为它们实际上是全局变量 - 根本不需要。

在 PHP 5.2(及更早版本)中,如果您需要在回调中调用上下文,您可以通过使用它自己的类来创建上下文:

class CallContext
{
}

例如,您有 sort 的比较函数:

class CallContext
{
    ...
    public function compare($a, $b)
    {
         return $this->weight($a) - $this->weight($b);
    }

    public function getCallback()
    {
         return array($this, 'compare');
    }
    ...
}

该函数可以用作以下回调 usort 然后:

$context = new CallContext();

usort($array, $context->getCallback());

非常简单。 CallContext::weight 的私有(private)实现仍然失踪,从你的问题我们知道它需要一些分类数据和信息。例如,每条记录中国家/地区 ID 的键名。假设记录是 Stdclass 对象,因此为了获得一条记录的权重,上下文类需要知道属性的名称、您自己定义的排序顺序以及未在自定义排序顺序(其他的,其余的)。

这些配置值由constructor 函数(简称​​ctor)给出,并存储为私有(private)成员。失踪的weight然后函数根据该信息将记录转换为排序值:

class CallContext
{
    private $property, $sortOrder, $sortOther;

    public function __construct($property, $sortOrder, $sortOther = 9999)
    {
        $this->property = $property;
        $this->sortOrder = $sortOrder;
        $this->sortOther = $sortOther;
    }

    private function weight($object) {
        if (!is_object($object)) {
            throw new InvalidArgumentException(sprintf('Not an object: %s.', print_r($object, 1)));
        }
        if (!isset($object->{$this->property})) {
            throw new InvalidArgumentException(sprintf('Property "%s" not found in object: %s.', $this->property, print_r($object, 1)));
        }
        $value = $object->{$this->property};
        return isset($this->sortOrder[$value])
               ? $this->sortOrder[$value]
               : $this->sortOther;
    }
    ...

用法现在扩展到以下内容:

$property = 'country';
$order = array(
    # country ID => sort key (lower is first)
    46 => 1,
    45 => 2
);
$context = new CallContext('country', $order);
usort($array, $context->getCallback());

使用相同的原理,您通常可以使用 use 转换任何 PHP 5.3 闭包。 PHP 5.2 的子句。来自 use 的变量子句成为注入(inject)构造的私有(private)成员。

这个变体不仅阻止了静态的使用,它还使每个元素都有一些映射变得可见,并且由于两个元素被平等对待,它使用了一些 weight 的私有(private)实现。与 usort 配合得很好的功能.

希望对您有所帮助。

关于php - 按权重值对多维数组进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11827663/

相关文章:

c++ - 合并排序代码调试

php - 循环以按字母顺序返回所有 Woocommerce 产品标签

python - 按最小索引号对 Pandas 数据框组进行排序,然后根据第三列对组内的所有其他列重新排序

php - 使用参数计算行数

php - 当我单击下一步时,基于条件的分页不起作用

php - SMTP 错误(220-我们未授权使用此系统传输未经请求的 220 和/或批量电子邮件。)

javascript - 求和特定数组值取决于其他数组的索引值列表

php - Laravel 项目面板 orderby 在他们的优先级上不起作用

java - 如何将二维数组中的值复制到双向链表

jquery - 等于 jQuery 对象的变量