如何通过PHP中内部数组的某个字段对多维数组进行排序?

时间:2010-03-11 16:49:12

标签: php arrays sorting multidimensional-array

假设我有一个模拟数据库表的数组。每个数组元素代表一行,每行内是另一个包含字段名称和值的数组。

Array
(
    [0] => Array
        (
            [name] => 'Sony TV'
            [price] => 600.00
        )

    [1] => Array
        (
            [name] => 'LG TV'
            [price] => 350.00
        )

    [2] => Array
        (
            [name] => 'Samsung TV'
            [price] => 425.00
        )  
}

我想要做的是按价格对行(外部数组元素)进行排序。以下是我想要实现的一个例子:

Array
(
    [0] => Array
        (
            [name] => 'LG TV'
            [price] => 350.00
        )

    [1] => Array
        (
            [name] => 'Samsung TV'
            [price] => 425.00
        )

    [2] => Array
        (
            [name] => 'Sony TV'
            [price] => 600.00
        )        
}

如您所见,我不需要保留外部数组的键。

9 个答案:

答案 0 :(得分:35)

您需要使用usort,这是一个通过用户定义的函数对数组进行排序的函数。类似的东西:

function cmp($a, $b)
{
    if ($a["price"] == $b["price"]) {
        return 0;
    }
    return ($a["price"] < $b["price"]) ? -1 : 1;
}

usort($yourArray,"cmp")

答案 1 :(得分:14)

您可以使用usort()

function sort($a, $b) {
    if ($a['price'] == $b['price']) return 0;
    return ($a['price'] > $b['price']) ? 1 : -1;
}

usort($array, 'sort');

如果您创建这样的类以重用代码,那就更好了:

class FieldSorter {
    public $field;

    function __construct($field) {
        $this->field = $field;
    }

    function cmp($a, $b) {
        if ($a[$this->field] == $b[$this->field]) return 0;
        return ($a[$this->field] > $b[$this->field]) ? 1 : -1;
    }
}

$sorter = new FieldSorter('price');    
usort($array, array($sorter, "cmp"));

这样,您可以轻松地按其他字段排序。

虽然您说不必保留外部数组的键,但您可以使用uasort()代替usort轻松实现此目的。

答案 2 :(得分:12)

这只是一个班轮

array_multisort( array_column($yourArray, "price"), SORT_ASC, $yourArray );

你也可以在这里找到它:http://php.net/manual/en/function.array-multisort.php

搜索&#34; array_column&#34;在该手册页上。

答案 3 :(得分:2)

这与接受的答案基本相同,但多年来在PHP中添加了一些新功能,以便更方便地使用usort

$column = 'price';
usort($table, function($a, $b) use ($column) {
    return $a[$column] <=> $b[$column];
});

现在可以使用anonymous function进行比较回调(从PHP 5.3开始),PHP 7引入了combined comparison operator<=>),它允许您减少比较逻辑

if ($a['price'] == $b['price']) return 0;
return ($a['price'] > $b['price']) ? 1 : -1;

到单个表达式

return $a[$column] <=> $b[$column];

答案 4 :(得分:1)

您可以将usort函数与回调

一起使用

http://www.php.net/manual/en/function.usort.php

答案 5 :(得分:1)

这个问题有点陈旧,但将来会留下答案。

来自php.net-Multisort 功能我们可以使用下面的代码;

    $data= [['volume' => 67, 'edition' => 2],['volume' => 85, 'edition' => 6],...];
foreach ($data as $key => $row) {
    $volume[$key]  = $row['volume'];
    $edition[$key] = $row['edition'];
}
array_multisort($volume, SORT_DESC, $edition, SORT_ASC, $data);

以上是对手动更改排序列的数据进行静态排序。

有关更具动态性和更强大的示例,请参阅下文;

假设我有以下数据;

$data   = [[1, 'Amanda', 'Wright', 'awright0@usnews.com', 'Female', '135.114.57.89', 31237],
           [2, 'Theresa', 'Larson', 'tlarson1@51.la', 'Female', '207.108.96.210', 91011],
           [3, 'Walter', 'Kennedy', 'wkennedy2@baidu.com', 'Male', '199.147.223.56', 50114],
           [4, 'Andrea', 'Richards', 'arichards3@google.nl', 'Female', '230.195.124.95', 76489],
           [5, 'Carol', 'Jones', 'cjones4@elegantthemes.com', 'Female', '250.197.111.90', 56501],
           [6, 'Alice', 'Freeman', 'afreeman5@elegantthemes.com', 'Female', '52.195.252.131', 77170],
           [7, 'Gerald', 'Fisher', 'gfisher6@slashdot.org', 'Male', '81.2.22.62', 75625],....]

如果我们需要对上面的数组数据进行排序,那么我们可以使用语法在数组中设置排序顺序;

 $qTable[$index]=$sort_order;
E.g. $qTable=[1=>'asc',4=>'desc',3=>'asc'];

这意味着对第1列ASC,第4列DESC以及第3列ASC进行排序。 然后我们可以使用下面的函数对多维数据库数据进行排序;

   function sortMulti($data, $orders)
    {
        $args = [];
        foreach ($data as $key => $row) {
            foreach ($orders as $index => $order) {
                if (!isset($row[$index])) continue; //Ignore if column does'nt exist
                $args[$index]['d'][$key] = $row[$index]; //Get all values within the column
                $args[$index]['o']       = 'desc' == strtolower($order) ? SORT_DESC : SORT_ASC; //Get the Sort order 'ASC' is the default
            }
        }
        $p = [];
//Below we need to organize our entries as arguments for array_multisort
        foreach ($args as $arg) {
            $p[] = $arg['d'];
            $p[] = $arg['o'];
//Below we need to check if column contains only numeric or not.
//If all values are numeric, then we use numeric sort flag, otherwise NATURAL
//Manipulate for more conditions supported
            $p[] = count($arg['d']) == count(array_filter($arg['d'], 'is_numeric')) ? SORT_NUMERIC : SORT_NATURAL;
        }
        $p[] = &$data; //Pass by reference
        call_user_func_array('array_multisort', $p); //Call Php's own multisort with parameters in required order.
        return $data; //Our final array sorted.
    }

然后我们可以使用它如下;

$data=[[...],[...],...];
$order=[1=>'asc',4=>'desc',3=>'asc'];

$sorted=sortMulti($data,$order);

对于键值数组数据E.g. $data=[['c1'=>1212,'c2'=>'mynames'],...]; 将订单用作$order=['c1'=>'desc','c10'=>'asc'];

我用1000个记录的数组测试了上面的内容。 希望它可以帮到某人。

答案 6 :(得分:0)

usort 的替代方法是创建一个数组,该数组索引要排序的数组,并由您要排序的数据编制索引。

在下面的代码段中, $ customAttributes 是一个对象数组,我想按 name 排序。首先创建 $ sort ,由 name 编制索引并包含相应 $ customAttributes 元素的数组索引。

$sort = [];
foreach( $customAttributes as $c => $ca )
{
    $sort[$ca->name] = $c;
}
然后使用

ksort 按键对数组进行排序。

ksort( $sort );

$ sort 数组进行排序后,迭代它并创建 $ ordered 数组。

$ordered = [];
foreach( $sort as $s )
{
    $ordered[] = $customAttributes[$s];
}

我喜欢这个解决方案,因为函数调用比使用回调更少。

答案 7 :(得分:0)

您可以自己创建一个功能,如下面的

私有函数orderArrayBycolumn($ array,$ column){

    $newArray = [];
    foreach ($array as $key => $value) {
        $newArray[$value[$column]] = $value;
    }

    $array = [];

    ksort($newArray);

    foreach ($newArray as $key => $value) {
        $array[] = $value;
    }      

    return $array;
}

答案 8 :(得分:0)

我只想添加几个...

@ rf1234的答案可能就是我想要的(因为我读到某个地方for((i=0; i < $number; i++)); do ...胜过array_multisort(),但我个人没有对它们进行基准测试),但是排序方向不必是声明,因为默认方向是ASC。

代码:(Demo

usort()

@ Don'tPanic通过$column = 'price'; array_multisort(array_column($array, $column), $array); var_export($array); 与飞船操作员的回答也很有吸引力。从PHP7.4起,可以使用箭头函数语法来减少语法并删除usort()表达式。这项技术允许use()在没有$column的情况下自由输入函数范围。

代码:(Demo

use()

我推荐这些正确,有效,直接的解决方案之一。