【问题标题】:PHP Sort Array By SubArray ValuePHP按子数组值排序数组
【发布时间】:2011-01-29 11:13:57
【问题描述】:

我有以下数组结构:

Array
        (
            [0] => Array
                (
                    [configuration_id] => 10
                    [id] => 1
                    [optionNumber] => 3
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )

            [1] => Array
                (
                    [configuration_id] => 9
                    [id] => 1
                    [optionNumber] => 2
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )

            [2] => Array
                (
                    [configuration_id] => 8
                    [id] => 1
                    [optionNumber] => 1
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )
    )

根据optionNumber,以增量方式对数组进行排序的最佳方法是什么?

所以结果看起来像:

Array
        (
            [0] => Array
                (
                    [configuration_id] => 8
                    [id] => 1
                    [optionNumber] => 1
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )

            [1] => Array
                (
                    [configuration_id] => 9
                    [id] => 1
                    [optionNumber] => 2
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )

            [2] => Array
                (
                    [configuration_id] => 10
                    [id] => 1
                    [optionNumber] => 3
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )
    )

【问题讨论】:

    标签: php arrays sorting


    【解决方案1】:

    使用usort

    function cmp_by_optionNumber($a, $b) {
      return $a["optionNumber"] - $b["optionNumber"];
    }
    
    ...
    
    usort($array, "cmp_by_optionNumber");
    

    在 PHP ≥5.3 中,您应该使用 anonymous function 代替:

    usort($array, function ($a, $b) {
        return $a['optionNumber'] - $b['optionNumber'];
    });
    

    请注意,上面的两个代码都假定$a['optionNumber'] 是一个整数。如果是字符串,请使用@St. John Johnson's solution


    在 PHP ≥7.0 中,使用spaceship operator <=> 代替减法来防止溢出/截断问题。

    usort($array, function ($a, $b) {
        return $a['optionNumber'] <=> $b['optionNumber'];
    });
    

    【讨论】:

    • 这对我没有帮助,因为 usort 需要我提供一个可以使用的功能 - 这是我无法理解的难点
    • 好吧,他只是给了你使用的功能。而且您将不得不接受并不总是有内置函数可以做您想做的事情,您必须自己编写。比较函数只需要返回 1、0 或 -1 来指示两个元素的排序顺序。
    • 我进一步研究了 usort,它实际上很酷。我为上面的那个写了一个简单的比较函数,但是错过了'=='。谢谢大家的帮助
    • 现在也作为闭包:-- usort($array, function($a,$b){ return $b["optionNumber"] - $a["optionNumber"]; });
    • @KiloumapL'artélon 如果结果是&lt; 0,它告诉排序函数a 应该出现在b 之前。如果是&gt; 0,那么b 应该出现在a 之前。
    【解决方案2】:

    使用usort

     usort($array, 'sortByOption');
     function sortByOption($a, $b) {
       return strcmp($a['optionNumber'], $b['optionNumber']);
     }
    

    【讨论】:

    • @BenSinclair,那是因为 Kenny 的解决方案是针对数字的,这个解决方案是针对字符串的。他们都是正确的 :-) 对于这个替代方案 +1。
    • 对于不区分大小写的排序,使用 strcasecmp 而不是 strcmp
    • 我们能否定义数组中二阶的键意味着我们首先使用 optionNumber 进行排序,然后使用 lastUpdated 进行排序。这怎么能行?
    【解决方案3】:

    我使用了KennyTMAJ Quick 的两种解决方案,并提出了一个可以在许多情况下帮助解决此问题的功能,例如使用ASC 或DESC 排序或保留键 或者如果您有对象作为数组的子项

    这里是这个函数(适用于 PHP7 及更高版本,因为 spaceship 运算符):

    /**
     * @param array $array
     * @param string $value
     * @param bool $asc - ASC (true) or DESC (false) sorting
     * @param bool $preserveKeys
     * @return array
     * */
    function sortBySubValue($array, $value, $asc = true, $preserveKeys = false)
    {
        if ($preserveKeys) {
            $c = [];
            if (is_object(reset($array))) {
                foreach ($array as $k => $v) {
                    $b[$k] = strtolower($v->$value);
                }
            } else {
                foreach ($array as $k => $v) {
                    $b[$k] = strtolower($v[$value]);
                }
            }
            $asc ? asort($b) : arsort($b);
            foreach ($b as $k => $v) {
                $c[$k] = $array[$k];
            }
            $array = $c;
        } else {
            if (is_object(reset($array))) {
                usort($array, function ($a, $b) use ($value, $asc) {
                    return $a->{$value} == $b->{$value} ? 0 : ($a->{$value} <=> $b->{$value}) * ($asc ? 1 : -1);
                });
            } else {
                usort($array, function ($a, $b) use ($value, $asc) {
                    return $a[$value] == $b[$value] ? 0 : ($a[$value] <=> $b[$value]) * ($asc ? 1 : -1);
                });
            }
        }
    
        return $array;
    }
    

    用法:

    sortBySubValue($array, 'optionNumber', true, false);
    

    编辑

    第一部分可以用uasort()重写,函数会更短(适用于PHP7及更高版本,因为有spaceship运算符):

    /**
     * @param array $array
     * @param string $value
     * @param bool $asc - ASC (true) or DESC (false) sorting
     * @param bool $preserveKeys
     * @return array
     * */
    function sortBySubValue($array, $value, $asc = true, $preserveKeys = false)
    {
        if (is_object(reset($array))) {
            $preserveKeys ? uasort($array, function ($a, $b) use ($value, $asc) {
                return $a->{$value} == $b->{$value} ? 0 : ($a->{$value} <=> $b->{$value}) * ($asc ? 1 : -1);
            }) : usort($array, function ($a, $b) use ($value, $asc) {
                return $a->{$value} == $b->{$value} ? 0 : ($a->{$value} <=> $b->{$value}) * ($asc ? 1 : -1);
            });
        } else {
            $preserveKeys ? uasort($array, function ($a, $b) use ($value, $asc) {
                return $a[$value] == $b[$value] ? 0 : ($a[$value] <=> $b[$value]) * ($asc ? 1 : -1);
            }) : usort($array, function ($a, $b) use ($value, $asc) {
                return $a[$value] == $b[$value] ? 0 : ($a[$value] <=> $b[$value]) * ($asc ? 1 : -1);
            });
        }
        return $array;
    }
    

    【讨论】:

    • 这是这里最好最有用的答案,应该在最上面;)
    • @EdiBudimilic 谢谢你,我很感激!顺便说一句,我已经更新了我的答案并添加了这个函数的更短版本:)
    • 为了使这项工作适合我,在比较 $a$b 值时,我必须使用 &gt;(大于)而不是 -(减号),因为我正在比较字符串。不过仍然有效。
    • @James 你是对的。我更改了答案并添加了宇宙飞船运算符()的使用。现在它应该可以正常工作了。
    • 有没有办法让这个大小写不敏感?
    【解决方案4】:

    使用array_multisort()、array_map()

    array_multisort(array_map(function($element) {
          return $element['optionNumber'];
      }, $array), SORT_ASC, $array);
    
    print_r($array);
    

    DEMO

    【讨论】:

    • 这很容易工作。谢谢你。我所要做的就是更改我的列名,它就奏效了。
    • 这也保留了父数组的键
    • 我知道这个问题现在有点老了,但我有一个问题:我看到它确实有效,但它是如何工作的?我已经阅读了 php.net 上的 array_multisort 文档,但这对我来说仍然没有多大意义。
    【解决方案5】:

    使用上述功能时会删除键。如果键很重要,下面的函数会维护它……但是 foreach 循环效率很低。

    function subval_sort($a,$subkey) {
        foreach($a as $k=>$v) {
            $b[$k] = strtolower($v[$subkey]);
        }
        asort($b);
        foreach($b as $key=>$val) {
            $c[$key] = $a[$key];
        }
        return $c;
    }
    $array = subval_sort($array,'optionNumber');
    

    如果要从高到低,请使用 arsort 而不是 asort。

    代码信用:http://www.firsttube.com/read/sorting-a-multi-dimensional-array-with-php/

    【讨论】:

      【解决方案6】:

      PHP 5.3+

      usort($array, function($a,$b){ return $a['optionNumber']-$b['optionNumber'];} );
      

      【讨论】:

        【解决方案7】:

        使用array_multisortarray_column 的单行解决方案。

        //your array
        $yourarray = Array
                  (
                   "0" => Array
                          (
                            "configuration_id" => 10,
                            "id" => 1,
                            "optionNumber" => 3,
                            "optionActive" => 1,
                            "lastUpdated" => "2010-03-17 15:44:12"
                          ),
                   "1" => Array
                          (
                            "configuration_id" => 9,
                            "id" => 1,
                            "optionNumber" => 2,
                            "optionActive" => 1,
                            "lastUpdated" => "2010-03-17 15:44:12"
                          ),
                   "2" => Array
                          (
                            "configuration_id" => 8,
                            "id" => 1,
                            "optionNumber" => 1,
                            "optionActive" => 1,
                            "lastUpdated" => "2010-03-17 15:44:12"
                          )
        );
        
        //access optionNumber in the child arrays using array_column
        array_multisort(array_column($yourarray, 'optionNumber'), SORT_ASC, $yourarray);
        
        //print out preformatted
        echo "<pre>"; print_r($images); echo "</pre>";
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-04-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-10-15
          • 2011-09-23
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多