如何按PHP中给定键的值对关联数组进行排序?

时间:2009-10-20 22:47:27

标签: php sorting

鉴于此数组:

$inventory = array(

   array("type"=>"fruit", "price"=>3.50),
   array("type"=>"milk", "price"=>2.90),
   array("type"=>"pork", "price"=>5.43),

);

我想按价格排序$inventory元素来获取:

$inventory = array(

   array("type"=>"pork", "price"=>5.43),
   array("type"=>"fruit", "price"=>3.50),
   array("type"=>"milk", "price"=>2.90),

);

我该怎么做?

21 个答案:

答案 0 :(得分:504)

你是对的,你正在寻找的功能是array_multisort()

以下是直接从手册中获取的示例,并根据您的情况进行了调整:

$price = array();
foreach ($inventory as $key => $row)
{
    $price[$key] = $row['price'];
}
array_multisort($price, SORT_DESC, $inventory);
  

从PHP 5.5.0起,您可以使用array_column()而不是foreach

$price = array_column($inventory, 'price');

array_multisort($price, SORT_DESC, $inventory);

答案 1 :(得分:249)

PHP 7 +

从PHP 7开始,可以使用usortanonymous function使用spaceship operator来比较元素,从而简洁地完成此操作。

您可以按照以下方式进行升序排序:

usort($inventory, function ($item1, $item2) {
    return $item1['price'] <=> $item2['price'];
});

或者像这样的降序:

usort($inventory, function ($item1, $item2) {
    return $item2['price'] <=> $item1['price'];
});

要了解其工作原理,请注意usort采用用户提供的比较函数,该函数的行为如下(来自文档):

  

如果第一个参数被认为分别小于,等于或大于第二个参数,则比较函数必须返回小于,等于或大于零的整数。

还要注意宇宙飞船运营商<=>

  如果两个操作数相等,则

返回0;如果左边是更大,则返回1;如果右边更大,则返回-1

这正是usort所需要的。事实上,将<=>添加到https://wiki.php.net/rfc/combined-comparison-operator语言中的几乎所有理由都是它

  

使编写顺序回调用于usort()更容易


PHP 5.3 +

PHP 5.3引入了匿名函数,但还没有太空船运营商。我们仍然可以使用usort对数组进行排序,但它更冗长,更难理解:

usort($inventory, function ($item1, $item2) {
    if ($item1['price'] == $item2['price']) return 0;
    return $item1['price'] < $item2['price'] ? -1 : 1;
});

请注意,虽然处理整数值的比较器只返回值的差异(例如$item2['price'] - $item1['price'])是相当常见的,但在这种情况下我们不能安全地执行此操作。这是因为价格是问题提供者示例中的浮点数,但我们传递给usort的比较函数必须返回usort的整数才能正常工作:

  

从比较函数返回 非整数 值,例如float,将导致内部强制转换为回调返回值的整数。因此,诸如0.99和0.1之类的值都将被转换为整数值0,这将将这些值比较为相等。

在PHP 5.x中使用usort时,这是一个重要的陷阱! My original version of this answer犯了这个错误,然而我却在没有任何人注意到这个严重错误的情况下累积了数十个观点。像我这样的不熟练的人可以轻松搞砸比较器功能正是在PHP 7中将易于使用的太空船操作员添加到语言中的原因。

答案 2 :(得分:60)

虽然其他人已正确建议使用array_multisort(),但出于某种原因,似乎没有答案承认array_column()的存在,这可以大大简化解决方案。所以我的建议是:

array_multisort(array_column($inventory, 'price'), SORT_DESC, $inventory);

答案 3 :(得分:40)

由于数组元素本身是带有字符串键的数组,因此最好的办法是定义自定义比较函数。它非常快速和容易。试试这个:

function invenDescSort($item1,$item2)
{
    if ($item1['price'] == $item2['price']) return 0;
    return ($item1['price'] < $item2['price']) ? 1 : -1;
}
usort($inventory,'invenDescSort');
print_r($inventory);

产生以下内容:

Array
(
    [0] => Array
        (
            [type] => pork
            [price] => 5.43
        )

    [1] => Array
        (
            [type] => fruit
            [price] => 3.5
        )

    [2] => Array
        (
            [type] => milk
            [price] => 2.9
        )

)

答案 4 :(得分:23)

我结束了这个:

function sort_array_of_array(&$array, $subfield)
{
    $sortarray = array();
    foreach ($array as $key => $row)
    {
        $sortarray[$key] = $row[$subfield];
    }

    array_multisort($sortarray, SORT_ASC, $array);
}

只需调用该函数,传递数组和第二级数组字段的名称。 像:

sort_array_of_array($inventory, 'price');

答案 5 :(得分:15)

您可以将usort与匿名函数一起使用,例如

usort($inventory, function ($a, $b) { return strnatcmp($a['price'], $b['price']); });

答案 6 :(得分:9)

$inventory = 
    array(array("type"=>"fruit", "price"=>3.50),
          array("type"=>"milk", "price"=>2.90),
          array("type"=>"pork", "price"=>5.43),
          );

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

usort($inventory, "pricesort");
// uksort($inventory, "pricesort");

print("first: ".$inventory[0]['type']."\n\n");
// for usort(): prints milk (item with lowest price)
// for uksort(): prints fruit (item with key 0 in the original $inventory)

// foreach prints the same for usort and uksort.
foreach($inventory as $i){
  print($i['type'].": ".$i['price']."\n");
}

输出:

first: pork

pork: 5.43
fruit: 3.5
milk: 2.9

答案 7 :(得分:4)

在100 000条记录上进行了测试: 以秒为单位的时间(通过函数microtime计算)。 仅用于排序键位置的唯一值。

@Josh Davis的功能解决方案: 暂停时间:1.5768740177155

矿山解决方案: 暂停时间:0.094044923782349

<强>解决方案:

function SortByKeyValue($data, $sortKey, $sort_flags=SORT_ASC)
{
    if (empty($data) or empty($sortKey)) return $data;

    $ordered = array();
    foreach ($data as $key => $value)
        $ordered[$value[$sortKey]] = $value;

    ksort($ordered, $sort_flags);

    return array_values($ordered); *// array_values() added for identical result with multisort*
}

答案 8 :(得分:4)

来自Sort an array of associative arrays by value of given key in php

uasort(http://php.net/uasort)允许您通过自己定义的函数对数组进行排序。在你的情况下,这很简单:

$array = array(
  array('price'=>'1000.50','product'=>'test1'),
  array('price'=>'8800.50','product'=>'test2'),
  array('price'=>'200.0','product'=>'test3')
);

function cmp($a, $b) {
  return $a['price'] > $b['price'];
}

uasort($array, "cmp");

答案 9 :(得分:3)

对于 PHP 7 和更高版本。

/**
 * A method for sorting associative arrays by a key and a direction.
 * Direction can be ASC or DESC.
 *
 * @param $array
 * @param $key
 * @param $direction
 * @return mixed $array
 */
function sortAssociativeArrayByKey($array, $key, $direction){

    switch ($direction){
        case "ASC":
            usort($array, function ($first, $second) use ($key) {
                return $first[$key] <=> $second[$key];
            });
            break;
        case "DESC":
            usort($array, function ($first, $second) use ($key) {
                return $second[$key] <=> $first[$key];
            });
            break;
        default:
            break;
    }

    return $array;
}

用法:

$inventory = sortAssociativeArrayByKey($inventory, "price", "ASC");

答案 10 :(得分:2)

您可以尝试定义自己的比较函数,然后使用usort

答案 11 :(得分:2)

此功能可重复使用:

function usortarr(&$array, $key, $callback = 'strnatcasecmp') {
    uasort($array, function($a, $b) use($key, $callback) {
        return call_user_func($callback, $a[$key], $b[$key]);
    });
}

默认情况下,它在字符串值上运行良好,但如果您的所有值都是数字,则必须将number comparison function的回调作为参数。

答案 12 :(得分:2)

尝试一下:

$prices = array_column($inventory, 'price');
array_multisort($prices, SORT_DESC, $inventory);
print_r($inventory);

答案 13 :(得分:1)

//Just in one line custom function
function cmp($a, $b)
{
return (float) $a['price'] < (float)$b['price'];
}
@uasort($inventory, "cmp");
print_r($inventory);

//result

Array
(
[2] => Array
    (
        [type] => pork
        [price] => 5.43
    )

[0] => Array
    (
        [type] => fruit
        [price] => 3.5
    )

[1] => Array
    (
        [type] => milk
        [price] => 2.9
    )

)

答案 14 :(得分:1)

这是我很久以前发现并整理的一种方法。这很好用,并且可以快速更改为接受对象。

/**
 * A method for sorting arrays by a certain key:value.
 * SortByKey is the key you wish to sort by
 * Direction can be ASC or DESC.
 *
 * @param $array
 * @param $sortByKey
 * @param $sortDirection
 * @return array
 */
private function sortArray($array, $sortByKey, $sortDirection) {

    $sortArray = array();
    $tempArray = array();

    foreach ( $array as $key => $value ) {
        $tempArray[] = strtolower( $value[ $sortByKey ] );
    }

    if($sortDirection=='ASC'){ asort($tempArray ); }
        else{ arsort($tempArray ); }

    foreach ( $tempArray as $key => $temp ){
        $sortArray[] = $array[ $key ];
    }

    return $sortArray;

}

要更改对对象进行排序的方法,只需更改以下行:

$tempArray[] = strtolower( $value[ $sortByKey ] );$tempArray[] = strtolower( $value->$sortByKey );

只需运行该方法即可

sortArray($inventory,'price','ASC');

答案 15 :(得分:0)

如果您需要对不同大小写的字符串数组进行排序,这会将排序数组值更改为小写。

$data = [
    [
        'name' => 'jack',
        'eyeColor' => 'green'
    ],
    [
        'name' => 'Amy',
        'eyeColor' => 'brown'
    ],
    [   
        'name' => 'Cody',
        'eyeColor' => 'blue'
    ] 
];
function toLowerCase($a) { return strtolower($a); }
$sortArray = array_map("toLowerCase",array_column($data, 'name'));
array_multisort($sortArray, SORT_ASC, $data);

答案 16 :(得分:0)

我这样使用uasort

<?php
$users = [
    [
        'username' => 'joe',
        'age' => 11
    ],
    [
        'username' => 'rakoto',
        'age' => 21
    ],
    [
        'username' => 'rabe',
        'age' => 17
    ],
    [
        'username' => 'fy',
        'age' => 19
    ],    
];


uasort($users, function ($item, $compare) {
    return $item['username'] >= $compare['username']; 
});

var_dump($users);

答案 17 :(得分:-1)

完成动态功能 我跳到这里进行关联数组排序,并在http://php.net/manual/en/function.sort.php上找到了这个惊人的功能。此函数非常动态,使用指定的键按升序和降序排序。

通过特定键对数组进行排序的简单函数。维护索引关联

<?php

function array_sort($array, $on, $order=SORT_ASC)
{
    $new_array = array();
    $sortable_array = array();

    if (count($array) > 0) {
        foreach ($array as $k => $v) {
            if (is_array($v)) {
                foreach ($v as $k2 => $v2) {
                    if ($k2 == $on) {
                        $sortable_array[$k] = $v2;
                    }
                }
            } else {
                $sortable_array[$k] = $v;
            }
        }

        switch ($order) {
            case SORT_ASC:
                asort($sortable_array);
            break;
            case SORT_DESC:
                arsort($sortable_array);
            break;
        }

        foreach ($sortable_array as $k => $v) {
            $new_array[$k] = $array[$k];
        }
    }

    return $new_array;
}

$people = array(
    12345 => array(
        'id' => 12345,
        'first_name' => 'Joe',
        'surname' => 'Bloggs',
        'age' => 23,
        'sex' => 'm'
    ),
    12346 => array(
        'id' => 12346,
        'first_name' => 'Adam',
        'surname' => 'Smith',
        'age' => 18,
        'sex' => 'm'
    ),
    12347 => array(
        'id' => 12347,
        'first_name' => 'Amy',
        'surname' => 'Jones',
        'age' => 21,
        'sex' => 'f'
    )
);

print_r(array_sort($people, 'age', SORT_DESC)); // Sort by oldest first
print_r(array_sort($people, 'surname', SORT_ASC)); // Sort by surname

答案 18 :(得分:-1)

$arr1 = array(

    array('id'=>1,'name'=>'aA','cat'=>'cc'),
    array('id'=>2,'name'=>'aa','cat'=>'dd'),
    array('id'=>3,'name'=>'bb','cat'=>'cc'),
    array('id'=>4,'name'=>'bb','cat'=>'dd')
);

$result1 = array_msort($arr1, array('name'=>SORT_DESC);

$result2 = array_msort($arr1, array('cat'=>SORT_ASC);

$result3 = array_msort($arr1, array('name'=>SORT_DESC, 'cat'=>SORT_ASC));


function array_msort($array, $cols)
{
    $colarr = array();
    foreach ($cols as $col => $order) {
    $colarr[$col] = array();
    foreach ($array as $k => $row) { $colarr[$col]['_'.$k] = strtolower($row[$col]); }
}

$eval = 'array_multisort(';

foreach ($cols as $col => $order) {
    $eval .= '$colarr[\''.$col.'\'],'.$order.',';
}

$eval = substr($eval,0,-1).');';
eval($eval);
$ret = array();
foreach ($colarr as $col => $arr) {
    foreach ($arr as $k => $v) {
        $k = substr($k,1);
        if (!isset($ret[$k])) $ret[$k] = $array[$k];
        $ret[$k][$col] = $array[$k][$col];
    }
}
return $ret;


} 

答案 19 :(得分:-2)

  <?php

$inventory = array(

   array("type"=>"fruit", "price"=>3.50),
   array("type"=>"milk", "price"=>2.90),
   array("type"=>"pork", "price"=>5.43),

);



function myfunc($a,$b){
return strnatcmp($a['price'],$b['price']);
}
$result=usort ($inventory,"myfunc");?>
<pre><?php print_r(array_reverse($inventory)); ?></pre>

简单的解决方案:)

输出是,

Array
(
    [0] => Array
        (
            [type] => pork
            [price] => 5.43
        )

    [1] => Array
        (
            [type] => fruit
            [price] => 3.5
        )

    [2] => Array
        (
            [type] => milk
            [price] => 2.9
        )

)

答案 20 :(得分:-3)

试试这个:

asort($array_to_sort, SORT_NUMERIC);

供参考,请参阅: http://php.net/manual/en/function.asort.php

在这里查看各种排序标志: http://www.php.net/manual/en/function.sort.php