如何通过PHP中的给定键的值来对关联数组的数组进行sorting?
给定这个数组:
$inventory = array( array("type"=>"fruit", "price"=>3.50), array("type"=>"milk", "price"=>2.90), array("type"=>"pork", "price"=>5.43), );
我想按价格对$inventory
的元素进行sorting得到:
$inventory = array( array("type"=>"pork", "price"=>5.43), array("type"=>"fruit", "price"=>3.50), array("type"=>"milk", "price"=>2.90), );
我该怎么做?
你是对的,你正在寻找的函数是array_multisort()
。
下面是从手册中直接获取的一个例子,并根据您的情况进行调整:
$price = array(); foreach ($inventory as $key => $row) { $price[$key] = $row['price']; } array_multisort($price, SORT_DESC, $inventory);
PHP 7+
从PHP 7开始,可以使用usort
简明地完成这个任务,使用太空船操作员比较元素的匿名函数 。
你可以像这样按升序sorting:
usort($inventory, function ($item1, $item2) { return $item1['price'] <=> $item2['price']; });
或者像这样降序sorting:
usort($inventory, function ($item1, $item2) { return $item2['price'] <=> $item1['price']; });
要理解这是如何工作的,请注意, usort
采用用户提供的比较函数,其行为必须如下(来自文档):
如果第一个参数分别小于,等于或大于第二个参数,则比较函数必须返回小于,等于或大于零的整数。
还要注意, <=>
,太空船的操作员,
如果两个操作数相等,则返回0;如果左边较大,则返回1;如果右边较大,则返回-1
这正是usort
需要的。 事实上,在https://wiki.php.net/rfc/combined-comparison-operator中添加;<=>
到语言的几乎所有的理由是它
使书面订购callback用于
usort()
更容易
PHP 5.3+
PHP 5.3引入了匿名函数,但是还没有太空船运营商。 我们仍然可以使用usort
来sorting我们的数组,但是它有点冗长和难以理解:
usort($inventory, function ($item1, $item2) { if ($item1['price'] == $item2['price']) return 0; return $item1['price'] < $item2['price'] ? -1 : 1; });
请注意,虽然处理整数值的比较器只是返回值的差异,例如$item2['price'] - $item1['price']
,但在这种情况下我们不能安全地做到这一点。 这是因为价格是问题提供者例子中的浮点数,但是我们传递给usort
的比较函数必须返回整数才能正常工作:
从比较函数返回非整数值(如float)将导致内部转换为callback的返回值的整数。 所以0.99和0.1这样的值都会被转换为0的整数值,这将比较这些值是相等的。
在PHP 5.x中使用usort
时,这是一个重要的陷阱! 我的这个答案的原始版本犯了这个错误,但我累积成千上万的意见显然没有人注意到严重的错误10 upvotes。 像我这样的缺乏智能可以使得比较函数变得简单, 正是在PHP 7中将易于使用的飞船运算符添加到语言中的原因。
由于您的数组元素是使用string键的数组本身,所以最好的办法是定义一个自定义的比较函数。 这是相当快速和容易做到的。 尝试这个:
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 ) )
我结束了这个:
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');
你可以使用匿名函数,例如
usort($inventory, function ($a, $b) { return strnatcmp($a['price'], $b['price']); });
而其他人正确地build议使用array_multisort()
,出于某种原因,似乎没有答案似乎承认array_column()
的存在,这可以大大简化解决scheme。 所以我的build议是:
array_multisort(array_column($inventory, 'price'), SORT_DESC, $inventory);
$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
在100 000条logging上进行了testing:以秒为单位的时间(通过函数microtime计算)。 仅用于sorting关键位置的唯一值。
@Josh Davisfunction解决scheme: 暂停时间 :1.5768740177155
排雷解决scheme: 暂停时间 :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* }
您可能会尝试定义您自己的比较函数,然后使用usort 。
//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 ) )
该function可重复使用:
function usortarr(&$array, $key, $callback = 'strnatcasecmp') { uasort($array, function($a, $b) use($key, $callback) { return call_user_func($callback, $a[$key], $b[$key]); }); }
它在默认情况下可以很好地处理string值,但是如果所有的值都是数字,则必须将callback函数作为数字比较函数 。
完整的dynamic函数我跳过这里进行关联数组sorting,并在http://php.net/manual/en/function.sort.php上find了这个惊人的function。; 这个函数是非常dynamic的,按照指定的键升序和降序sorting。
简单的函数按特定键sorting数组。 保持索引关联
<?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
尝试这个:
asort($array_to_sort, SORT_NUMERIC);
参考见: http : //php.net/manual/en/function.asort.php
在这里看到各种sorting标志: http : //www.php.net/manual/en/function.sort.php
$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; }
<?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>
简单的解决scheme:)
输出是,
Array ( [0] => Array ( [type] => pork [price] => 5.43 ) [1] => Array ( [type] => fruit [price] => 3.5 ) [2] => Array ( [type] => milk [price] => 2.9 ) )
从在PHP中给定的键的值sorting关联数组的数组 :
$array = array('0'=>array('price'=>'1000.50','product'=>'test1'), '1'=>array('price'=>'8800.50','product'=>'test2'), '2'=>array('price'=>'200.0','product'=>'test3')); function cmp($a, $b) { $p1 = $a['price']; $p2 = $b['price']; return (float)$p1 > (float)$p2; } @uasort($array, "cmp");