按照一个属性对对象数组进行排序

662

如何根据对象数组中的某个字段(例如 namecount)进行排序?

Array
(
    [0] => stdClass Object
        (
            [ID] => 1
            [name] => Mary Jane
            [count] => 420
        )

    [1] => stdClass Object
        (
            [ID] => 2
            [name] => Johnny
            [count] => 234
        )

    [2] => stdClass Object
        (
            [ID] => 3
            [name] => Kathy
            [count] => 4354
        )

   ....

1
countname变量/动态的吗?还是开发人员静态地“知道”它们? - mickmackusa
23个回答

4

这里所有答案的缺点是它们使用了静态字段名称,因此我用面向对象编程风格编写了一个调整后的版本。假设您正在使用getter方法,您可以直接使用此类并使用字段名称作为参数。可能有人会发现它有用。

class CustomSort{

    public $field = '';

    public function cmp($a, $b)
    {
        /**
         * field for order is in a class variable $field
         * using getter function with naming convention getVariable() we set first letter to uppercase
         * we use variable variable names - $a->{'varName'} would directly access a field
         */
        return strcmp($a->{'get'.ucfirst($this->field)}(), $b->{'get'.ucfirst($this->field)}());
    }

    public function sortObjectArrayByField($array, $field)
    {
        $this->field = $field;
        usort($array, array("Your\Namespace\CustomSort", "cmp"));;
        return $array;
    }
} 

3
一个简单的替代方法是,允许您动态确定排序基于哪个字段:
$order_by = 'name';
usort($your_data, function ($a, $b) use ($order_by)
{
    return strcmp($a->{$order_by}, $b->{$order_by});
});

这是基于 Closure 类的匿名函数技术。该技术从 PHP 5.3 开始提供。


3
如果您需要进行基于本地的字符串比较,可以使用 strcoll 而不是 strcmp
请注意,如果需要设置区域信息,请先使用 setlocaleLC_COLLATE
  usort($your_data,function($a,$b){
    setlocale (LC_COLLATE, 'pl_PL.UTF-8'); // Example of Polish language collation
    return strcoll($a->name,$b->name);
  });

2
感谢您的启发,我也不得不添加一个外部$translator参数。
usort($listable_products, function($a, $b) {
    global $translator;
    return strcmp($a->getFullTitle($translator), $b->getFullTitle($translator));
});

2
如果您正在Codeigniter中使用此功能,可以使用以下方法:
usort($jobs, array($this->job_model, "sortJobs"));  // function inside Model
usort($jobs, array($this, "sortJobs")); // Written inside Controller.

@rmooney感谢您的建议。它确实对我有所帮助。


1
这个问题与Codeigniter有什么具体关系? - ggdx
此答案绝对无法帮助提问者对其数据进行排序。该答案似乎完全忽略了所问的问题。 - mickmackusa

1

您可以使用Nspl中的sorted函数:

use function \nspl\a\sorted;
use function \nspl\op\propertyGetter;
use function \nspl\op\methodCaller;

// Sort by property value
$sortedByCount = sorted($objects, propertyGetter('count'));

// Or sort by result of method call
$sortedByName = sorted($objects, methodCaller('getName'));

请解释为什么OP需要一个完整的附加库来提供似乎可以通过内置函数解决的功能。 - ggdx

1
如果您只需要按一个字段排序,那么使用usort是一个不错的选择。但是,如果您需要按多个字段进行排序,则解决方案很快变得混乱。在这种情况下,可以使用YaLinqo库*,它为数组和对象实现了类似SQL的查询语法。它有一个漂亮的语法适用于所有情况:
$sortedByName         = from($objects)->orderBy('$v->name');
$sortedByCount        = from($objects)->orderBy('$v->count');
$sortedByCountAndName = from($objects)->orderBy('$v->count')->thenBy('$v->name');

在这里,'$v->count'function ($v) { return $v->count; }的简写(两者都可以使用)。这些方法链返回迭代器,但如果需要,您可以在末尾添加->toArray()来获取数组。 * 由我开发

1

这是我用于实用类的内容

class Util
{
    public static function sortArrayByName(&$arrayToSort, $meta) {
        usort($arrayToSort, function($a, $b) use ($meta) {
            return strcmp($a[$meta], $b[$meta]);
        });
    }
}

呼叫它:
Util::sortArrayByName($array, "array_property_name");

1
$array[0] = array('key_a' => 'z', 'key_b' => 'c');
$array[1] = array('key_a' => 'x', 'key_b' => 'b');
$array[2] = array('key_a' => 'y', 'key_b' => 'a');

function build_sorter($key) {
    return function ($a, $b) use ($key) {
        return strnatcmp($a[$key], $b[$key]);
    };
}

usort($array, build_sorter('key_b'));

这个答案缺少教育性的解释。 - mickmackusa

1
您可以像这样使用usort
如果您想按数字排序:
function cmp($a, $b)
{
    if ($a == $b) {
        return 0;
    }
    return ($a < $b) ? -1 : 1;
}

$a = array(3, 2, 5, 6, 1);

usort($a, "cmp");

Or Abc char:

function cmp($a, $b)
{
    return strcmp($a["fruit"], $b["fruit"]);
}

$fruits[0]["fruit"] = "lemons";
$fruits[1]["fruit"] = "apples";
$fruits[2]["fruit"] = "grapes";

usort($fruits, "cmp");

查看更多:https://www.php.net/manual/zh/function.usort.php


这个未经解释的答案完全忽略了原始问题是对对象数组进行排序的事实。 - mickmackusa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接