问题
I have array that I need to sort by another array form 2 fields zip code and approve
I am able to sort it by zip code but unable to do it with approved field so for eg
I need to sort by 60007,60001,60003,60002 (as per sortlike order) all zip code from 60007 and approved should come first so
$sortLike=array(60007,60001,60003,60002);
$array1= array(
array ('ID' => 138,'zip_code' => 60007,'approved' => 1),
array('ID' => 103,'zip_code' => 60007,'approved' => 0),
array('ID' => 114,'zip_code' => 60007,'approved' => 1),
array('ID' => 105,'zip_code' => 60003,'approved' => 0),
array('ID' => 124,'zip_code' => 60002,'approved' => 0)
)
so 60007 and aproved should come first than 60007 with 0(unapproved) and than all 60001 approved than all 60001 unapproved(and so on as per $sortlike
) here is complete php code
<?php
$array1= array(
array ('ID' => 138,'zip_code' => 60007,'approved' => 1),
array('ID' => 103,'zip_code' => 60007,'approved' => 0),
array('ID' => 114,'zip_code' => 60007,'approved' => 1),
array('ID' => 105,'zip_code' => 60003,'approved' => 0),
array('ID' => 124,'zip_code' => 60002,'approved' => 0),
array('ID' => 104,'zip_code' => 60002,'approved' => 1),
array('ID' => 106,'zip_code' => 60001,'approved' => 0),
array('ID' => 188,'zip_code' => 60022,'approved' => 0),
array('ID' => 184,'zip_code' => 60022,'approved' => 1),
);
function sort_results ($a, $b) {
$sortLike=array(60007,60001,60003,60002);
if (!in_array ($a['zip_code'], $sortLike)) { return 1; } // Push unknown values at the end of the array
return array_search($a['zip_code'], $sortLike) > array_search($b['zip_code'], $sortLike);
}
usort ($array1, 'sort_results');
echo "<pre>";
print_r($array1);
echo "</pre>";
回答1:
I guess you're asking how you can also sort by 'approved'
, because that is currently missing in your code.
The solution to this question is to define an order in which the keys of your input array $array1
are checked.
So you need to check zip_code
at first. If you get a result != 0, you can return immediately. But if the result is == 0 (the zip codes are equal) you need to check the second key ('approved'
in your case).
$array1= array(
array ('ID' => 138,'zip_code' => 60007,'approved' => 1),
array('ID' => 103,'zip_code' => 60007,'approved' => 0),
array('ID' => 114,'zip_code' => 60007,'approved' => 1),
array('ID' => 105,'zip_code' => 60003,'approved' => 0),
array('ID' => 124,'zip_code' => 60002,'approved' => 0),
array('ID' => 104,'zip_code' => 60002,'approved' => 1),
array('ID' => 106,'zip_code' => 60001,'approved' => 0),
array('ID' => 188,'zip_code' => 60022,'approved' => 0),
array('ID' => 184,'zip_code' => 60022,'approved' => 1),
);
function sort_results ($a, $b) {
$sortLike=array(60007,60001,60003,60002);
if (!in_array ($a['zip_code'], $sortLike)) { return 1; } // Push unknown values at the end of the array
$zip_res = array_search($a['zip_code'], $sortLike) - array_search($b['zip_code'], $sortLike); // check zip_code order
if($zip_res == 0){ // if the zip_codes are equal
$zip_res = $b['approved'] - $a['approved']; // sort by the 'approved' key
}
return $zip_res;
}
//edit
You can use a lamda function to move $sortLike
out of the function like this (requires PHP >= 5.3):
$sortLike=array(60007,60001,60003,60002);
$sort_results = function ($a, $b) use ($sortLike){ // create lambda function with "use" keyword
if (!in_array ($a['zip_code'], $sortLike)) { return 1; } // Push unknown values at the end of the array
$zip_res = array_search($a['zip_code'], $sortLike) - array_search($b['zip_code'], $sortLike);
if($zip_res == 0){
$zip_res = $b['approved'] - $a['approved'];
}
return $zip_res;
};
usort ($array1,$sort_results); // pass lambda function in
echo "<pre>";
print_r($array1);
echo "</pre>";
die();
回答2:
usort($array_data, array($sort_obj = new cmpArray('array_key'), "cmp__"));
class cmpArray
{
var $key;
function __construct($key)
{
$this->key = $key;
}
function cmp__($a, $b)
{
$key = $this->key;
if($a[$key] == $b[$key])
return 0;
return (($a[$key] > $b[$key]) ? 1 : -1);
}
}
回答3:
<?php
$array1= array(
array ('ID' => 138,'zip_code' => 60007,'approved' => 1),
array('ID' => 103,'zip_code' => 60007,'approved' => 0),
array('ID' => 114,'zip_code' => 60007,'approved' => 1),
array('ID' => 105,'zip_code' => 60003,'approved' => 0),
array('ID' => 124,'zip_code' => 60002,'approved' => 0),
array('ID' => 104,'zip_code' => 60002,'approved' => 1),
array('ID' => 106,'zip_code' => 60001,'approved' => 0),
array('ID' => 188,'zip_code' => 60022,'approved' => 0),
array('ID' => 184,'zip_code' => 60022,'approved' => 1),
);
function sort_it ($a) {
$sortedarr = array();
$sortLike=array(60007,60001,60003,60002);
foreach($sortLike as $el){
array_push($sortedarr,getElements($a,$el));
}
}
function getElements($arr,$e){
$newarr = array();
foreach($arr as $val){
if($val['approved'] == '1' && $val['zip_code'] == $e){
$newarr[] = $val;
}
}
foreach($arr as $val){
if($val['approved'] == '0' && $val['zip_code'] == $e){
$newarr[] = $val;
}
}
return $newarr;
}
$array2 = sort_it($array1);
echo "<pre>";
print_r($array1);
echo "</pre>";
echo "<pre>";
print_r($array2);
echo "</pre>";
?>
回答4:
usort()
PHP < v7.4: (Demo)
$priorityZips = array_flip([60007, 60001, 60003, 60002]);
$priorityCount = count($priorityZips);
usort($rows, function($a, $b) use ($priorityZips, $priorityCount) {
return [
$priorityZips[$a['zip_code']] ?? $priorityCount,
$a['zip_code'],
$b['approved']
]
<=>
[
$priorityZips[$b['zip_code']] ?? $priorityCount,
$b['zip_code'],
$a['approved']
];
});
usort()
PHP >= v7.4: (Demo)
$priorityZips = array_flip([60007, 60001, 60003, 60002]);
$priorityCount = count($priorityZips);
usort($rows, fn($a, $b) =>
[
$priorityZips[$a['zip_code']] ?? $priorityCount,
$a['zip_code'],
$b['approved']
]
<=>
[
$priorityZips[$b['zip_code']] ?? $priorityCount,
$b['zip_code'],
$a['approved']
]
);
array_multisort()
PHP < v7.4: (Demo)
$priorityZips = array_flip([60007, 60001, 60003, 60002]);
$priorityCount = count($priorityZips);
array_multisort(
array_map(
function($row) use ($priorityZips, $priorityCount) {
return $priorityZips[$row['zip_code']] ?? $priorityCount;
},
$rows
),
array_column($rows, 'zip_code'),
array_column($rows, 'approved'),
SORT_DESC,
$rows
);
array_multisort()
PHP >= v7.4: (Demo)
$priorityZips = array_flip([60007, 60001, 60003, 60002]);
$priorityCount = count($priorityZips);
array_multisort(
array_map(
fn($row) => $priorityZips[$row['zip_code']] ?? $priorityCount,
$rows
),
array_column($rows, 'zip_code'),
array_column($rows, 'approved'),
SORT_DESC,
$rows
);
In my snippets above, I refer to your input array to be sorted as $rows
.
This task can be performed several ways, but I've shown a few that I feel are cleanest / most readable. If performance is critical in your application, I'll encourage you to benchmark using your own real data; otherwise choose the snippet that you are most comfortable maintaining long-term.
In PHP versions below 7.4, passing variables into custom function scopes is done using use()
. In PHP7.4 and higher, "arrow function syntax", strips away a fair chunk of syntax in the custom function and allows the entry of variables without use()
.
The "spaceship operator" / "three-way comparison operator" (<=>
) makes building multi-criteria sorting MUCH cleaner and concise versus a bunch of condition blocks. The spaceship operator will synchronously process the elements in the arrays and return the correctly evaluated -1
, 0
, or 1
. It will also treat numeric strings as numbers.
I flipped the lookup array of prioritized zipcodes to enable the "null coalescing operator" (??
) to swiftly return the priority value or else default to a number greater than the highest integer value in the lookup.
Regarding the structure of the usort arrays being compared, you may like to see this answer that goes into a bit more detail.
来源:https://stackoverflow.com/questions/25603313/usort-multisort-array-based-on-another-array