[英]Sorting Array of Std Class Objects by Custom Order (PHP)
I have an array of StdClass Objects that contain different Car Types (ex. Compact Car, Mid-Size Car, etc.). 我有一个包含不同汽车类型(例如紧凑型汽车,中型汽车等)的StdClass对象数组。 The array should be sorted in the following order:
数组应按以下顺序排序:
I'm having a problem with sorting the remaining cars by price. 我在按价格排序其余汽车时遇到问题。 I tried sorting by price first, and then the ordered list in the second usort but it's not working as expected.
我先尝试按价格排序,然后在第二次排序中尝试按顺序排序,但是它没有按预期工作。 Any help would be appreciated.
任何帮助,将不胜感激。 I posted a similar question earlier, but figured I'd repost a more organized version of the requirements.
我之前发布了类似的问题,但认为我会重新发布需求的更有条理的版本。
Input Array: 输入数组:
array (
0 =>
stdClass::__set_state(array(
'description' => 'Mid-Size SUV',
'codes' =>
array (
0 => 'IFAR',
),
'max_people' => '5',
'min_people' => '5',
'max_bags' => '4',
'min_bags' => '1',
'price' => '30.31',
)),
1 =>
stdClass::__set_state(array(
'description' => 'Standard-Size SUV',
'codes' =>
array (
0 => 'SFAR',
1 => 'RFAR',
),
'max_people' => '7',
'min_people' => '5',
'max_bags' => '4',
'min_bags' => '1',
'price' => '35.53',
)),
2 =>
stdClass::__set_state(array(
'description' => 'Economy Car',
'codes' =>
array (
0 => 'ECAR',
1 => 'EDAR',
),
'max_people' => '5',
'min_people' => '4',
'max_bags' => '2',
'min_bags' => '1',
'price' => '37.21',
)),
3 =>
stdClass::__set_state(array(
'description' => 'Specialty Vehicle',
'codes' =>
array (
0 => 'XXAR',
),
'max_people' => false,
'min_people' => false,
'max_bags' => '',
'min_bags' => '',
'price' => '36.72',
)),
4 =>
stdClass::__set_state(array(
'description' => 'Compact Car',
'codes' =>
array (
0 => 'CCAR',
1 => 'CDAR',
),
'max_people' => '5',
'min_people' => '4',
'max_bags' => '3',
'min_bags' => '1',
'price' => '37.21',
)),
5 =>
stdClass::__set_state(array(
'description' => 'Mid-Size Car',
'codes' =>
array (
0 => 'ICAR',
1 => 'IDAR',
),
'max_people' => '5',
'min_people' => '5',
'max_bags' => '4',
'min_bags' => '1',
'price' => '39.46',
)),
6 =>
stdClass::__set_state(array(
'description' => 'Standard-Size Car',
'codes' =>
array (
0 => 'SCAR',
1 => 'SDAR',
),
'max_people' => '5',
'min_people' => '5',
'max_bags' => '4',
'min_bags' => '1',
'price' => '41.77',
)),
7 =>
stdClass::__set_state(array(
'description' => 'Minivan',
'codes' =>
array (
0 => 'MVAR',
),
'max_people' => '7',
'min_people' => '7',
'max_bags' => '5',
'min_bags' => '2',
'price' => '43.18',
)),
8 =>
stdClass::__set_state(array(
'description' => 'Full-Size Car',
'codes' =>
array (
0 => 'FCAR',
1 => 'FDAR',
),
'max_people' => '5',
'min_people' => '5',
'max_bags' => '4',
'min_bags' => '1',
'price' => '43.50',
)),
9 =>
stdClass::__set_state(array(
'description' => 'Compact SUV',
'codes' =>
array (
0 => 'CFAR',
),
'max_people' => '5',
'min_people' => '5',
'max_bags' => '3',
'min_bags' => '3',
'price' => '46.42',
)),
10 =>
stdClass::__set_state(array(
'description' => 'Full-Size Hybrid',
'codes' =>
array (
0 => 'FCAH',
),
'max_people' => false,
'min_people' => false,
'max_bags' => '',
'min_bags' => '',
'price' => '48.00',
)),
11 =>
stdClass::__set_state(array(
'description' => 'Standard-Size Convertible',
'codes' =>
array (
0 => 'STAR',
),
'max_people' => '4',
'min_people' => '4',
'max_bags' => '4',
'min_bags' => '1',
'price' => '48.39',
)),
12 =>
stdClass::__set_state(array(
'description' => 'Premium Car',
'codes' =>
array (
0 => 'PCAR',
),
'max_people' => '5',
'min_people' => '5',
'max_bags' => '4',
'min_bags' => '2',
'price' => '48.72',
)),
13 =>
stdClass::__set_state(array(
'description' => 'Sports Car',
'codes' =>
array (
0 => 'XSAR',
1 => 'SSAR',
),
'max_people' => '5',
'min_people' => '4',
'max_bags' => '3',
'min_bags' => '1',
'price' => '48.72',
)),
14 =>
stdClass::__set_state(array(
'description' => 'Luxury Car',
'codes' =>
array (
0 => 'LCAR',
1 => 'LDAR',
),
'max_people' => '5',
'min_people' => '5',
'max_bags' => '5',
'min_bags' => '1',
'price' => '52.16',
)),
15 =>
stdClass::__set_state(array(
'description' => 'Full-Size SUV',
'codes' =>
array (
0 => 'FFAR',
),
'max_people' => '8',
'min_people' => '7',
'max_bags' => '4',
'min_bags' => '2',
'price' => '52.92',
)),
16 =>
stdClass::__set_state(array(
'description' => 'Compact Convertible',
'codes' =>
array (
0 => 'CTAR',
),
'max_people' => '4',
'min_people' => '4',
'max_bags' => '1',
'min_bags' => '1',
'price' => '91.17',
)),
17 =>
stdClass::__set_state(array(
'description' => 'Premium SUV',
'codes' =>
array (
0 => 'PFAR',
1 => 'UFAR',
),
'max_people' => '7',
'min_people' => '5',
'max_bags' => '5',
'min_bags' => '1',
'price' => '92.64',
)),
18 =>
stdClass::__set_state(array(
'description' => 'Specialty Car',
'codes' =>
array (
0 => 'XCAR',
),
'max_people' => '5',
'min_people' => '5',
'max_bags' => '3',
'min_bags' => '3',
'price' => '94.42',
)),
19 =>
stdClass::__set_state(array(
'description' => 'Mid-Size Convertible',
'codes' =>
array (
0 => 'ITAR',
),
'max_people' => '4',
'min_people' => '4',
'max_bags' => '2',
'min_bags' => '2',
'price' => '97.98',
)),
20 =>
stdClass::__set_state(array(
'description' => 'Full-Size Van',
'codes' =>
array (
0 => 'FVAR',
),
'max_people' => '15',
'min_people' => '12',
'max_bags' => '5',
'min_bags' => '1',
'price' => '90.38',
)),
21 =>
stdClass::__set_state(array(
'description' => 'Luxury SUV',
'codes' =>
array (
0 => 'LFAR',
),
'max_people' => '5',
'min_people' => '5',
'max_bags' => '3',
'min_bags' => '3',
'price' => '113.66',
)),
22 =>
stdClass::__set_state(array(
'description' => 'Premium Convertible',
'codes' =>
array (
0 => 'PTAR',
),
'max_people' => '4',
'min_people' => '4',
'max_bags' => '1',
'min_bags' => '1',
'price' => '121.15',
)),
23 =>
stdClass::__set_state(array(
'description' => 'Luxury Convertible',
'codes' =>
array (
0 => 'LTAR',
),
'max_people' => '4',
'min_people' => '4',
'max_bags' => '1',
'min_bags' => '1',
'price' => '129.01',
)),
24 =>
stdClass::__set_state(array(
'description' => 'Premium Van',
'codes' =>
array (
0 => 'PVAR',
),
'max_people' => '15',
'min_people' => '15',
'max_bags' => '1',
'min_bags' => '1',
'price' => '159.49',
)),
25 =>
stdClass::__set_state(array(
'description' => 'Specialty Convertible',
'codes' =>
array (
0 => 'XTAR',
),
'max_people' => '4',
'min_people' => '4',
'max_bags' => '2',
'min_bags' => '2',
'price' => '307.64',
)),
)
Code: 码:
$order = [
'Economy Car' => 1,
'Compact Car' => 2,
'Mid-Size Car' => 3,
'Standard-Size Car' => 4,
'Full-Size Car' => 5,
'Premium Car' => 6,
'Luxury Car' => 7,
'Standard-Size Convertible' => 8,
'Mid-Size SUV' => 9,
'Standard SUV' => 10,
'Full-Size SUV' => 11,
'Minivan' => 12
];
usort($car_types,function($a, $b) {
return $a->price == $b->price ? 0 : $a->price > $b->price;
});
usort($car_types, function($a, $b) use ($order) {
$a_set = intval(isset($order[$a->description]));
$b_set = intval(isset($order[$b->description]));
return $a_set === $b_set && $a_set === 1
? $order[$a->description] - $order[$b->description]
: $b_set - $a_set;
});
New Output: 新输出:
Array
(
[0] => stdClass Object
(
[description] => Economy Car
[codes] => Array
(
[0] => ECAR
[1] => EDAR
)
[max_people] => 5
[min_people] => 4
[max_bags] => 2
[min_bags] => 1
[price] => 37.21
)
[1] => stdClass Object
(
[description] => Compact Car
[codes] => Array
(
[0] => CCAR
[1] => CDAR
)
[max_people] => 5
[min_people] => 4
[max_bags] => 3
[min_bags] => 1
[price] => 37.21
)
[2] => stdClass Object
(
[description] => Mid-Size Car
[codes] => Array
(
[0] => ICAR
[1] => IDAR
)
[max_people] => 5
[min_people] => 5
[max_bags] => 4
[min_bags] => 1
[price] => 39.46
)
[3] => stdClass Object
(
[description] => Standard-Size Car
[codes] => Array
(
[0] => SCAR
[1] => SDAR
)
[max_people] => 5
[min_people] => 5
[max_bags] => 4
[min_bags] => 1
[price] => 41.77
)
[4] => stdClass Object
(
[description] => Full-Size Car
[codes] => Array
(
[0] => FCAR
[1] => FDAR
)
[max_people] => 5
[min_people] => 5
[max_bags] => 4
[min_bags] => 1
[price] => 43.50
)
[5] => stdClass Object
(
[description] => Premium Car
[codes] => Array
(
[0] => PCAR
)
[max_people] => 5
[min_people] => 5
[max_bags] => 4
[min_bags] => 2
[price] => 48.72
)
[6] => stdClass Object
(
[description] => Luxury Car
[codes] => Array
(
[0] => LCAR
[1] => LDAR
)
[max_people] => 5
[min_people] => 5
[max_bags] => 5
[min_bags] => 1
[price] => 52.16
)
[7] => stdClass Object
(
[description] => Standard-Size Convertible
[codes] => Array
(
[0] => STAR
)
[max_people] => 4
[min_people] => 4
[max_bags] => 4
[min_bags] => 1
[price] => 48.39
)
[8] => stdClass Object
(
[description] => Mid-Size SUV
[codes] => Array
(
[0] => IFAR
)
[max_people] => 5
[min_people] => 5
[max_bags] => 4
[min_bags] => 1
[price] => 30.31
)
[9] => stdClass Object
(
[description] => Standard-Size SUV
[codes] => Array
(
[0] => SFAR
[1] => RFAR
)
[max_people] => 7
[min_people] => 5
[max_bags] => 4
[min_bags] => 1
[price] => 35.53
)
[10] => stdClass Object
(
[description] => Full-Size SUV
[codes] => Array
(
[0] => FFAR
)
[max_people] => 8
[min_people] => 7
[max_bags] => 4
[min_bags] => 2
[price] => 52.92
)
[11] => stdClass Object
(
[description] => Minivan
[codes] => Array
(
[0] => MVAR
)
[max_people] => 7
[min_people] => 7
[max_bags] => 5
[min_bags] => 2
[price] => 43.18
)
[12] => stdClass Object
(
[description] => Specialty Vehicle
[codes] => Array
(
[0] => XXAR
)
[max_people] =>
[min_people] =>
[max_bags] =>
[min_bags] =>
[price] => 36.72
)
[13] => stdClass Object
(
[description] => Compact SUV
[codes] => Array
(
[0] => CFAR
)
[max_people] => 5
[min_people] => 5
[max_bags] => 3
[min_bags] => 3
[price] => 46.42
)
[14] => stdClass Object
(
[description] => Sports Car
[codes] => Array
(
[0] => XSAR
[1] => SSAR
)
[max_people] => 5
[min_people] => 4
[max_bags] => 3
[min_bags] => 1
[price] => 48.72
)
[15] => stdClass Object
(
[description] => Full-Size Hybrid
[codes] => Array
(
[0] => FCAH
)
[max_people] =>
[min_people] =>
[max_bags] =>
[min_bags] =>
[price] => 48.00
)
[16] => stdClass Object
(
[description] => Full-Size Van
[codes] => Array
(
[0] => FVAR
)
[max_people] => 15
[min_people] => 12
[max_bags] => 5
[min_bags] => 1
[price] => 90.38
)
[17] => stdClass Object
(
[description] => Compact Convertible
[codes] => Array
(
[0] => CTAR
)
[max_people] => 4
[min_people] => 4
[max_bags] => 1
[min_bags] => 1
[price] => 91.17
)
[18] => stdClass Object
(
[description] => Premium SUV
[codes] => Array
(
[0] => PFAR
[1] => UFAR
)
[max_people] => 7
[min_people] => 5
[max_bags] => 5
[min_bags] => 1
[price] => 92.64
)
[19] => stdClass Object
(
[description] => Specialty Car
[codes] => Array
(
[0] => XCAR
)
[max_people] => 5
[min_people] => 5
[max_bags] => 3
[min_bags] => 3
[price] => 94.42
)
[20] => stdClass Object
(
[description] => Mid-Size Convertible
[codes] => Array
(
[0] => ITAR
)
[max_people] => 4
[min_people] => 4
[max_bags] => 2
[min_bags] => 2
[price] => 97.98
)
[21] => stdClass Object
(
[description] => Luxury SUV
[codes] => Array
(
[0] => LFAR
)
[max_people] => 5
[min_people] => 5
[max_bags] => 3
[min_bags] => 3
[price] => 113.66
)
[22] => stdClass Object
(
[description] => Premium Convertible
[codes] => Array
(
[0] => PTAR
)
[max_people] => 4
[min_people] => 4
[max_bags] => 1
[min_bags] => 1
[price] => 121.15
)
[23] => stdClass Object
(
[description] => Luxury Convertible
[codes] => Array
(
[0] => LTAR
)
[max_people] => 4
[min_people] => 4
[max_bags] => 1
[min_bags] => 1
[price] => 129.01
)
[24] => stdClass Object
(
[description] => Premium Van
[codes] => Array
(
[0] => PVAR
)
[max_people] => 15
[min_people] => 15
[max_bags] => 1
[min_bags] => 1
[price] => 159.49
)
[25] => stdClass Object
(
[description] => Specialty Convertible
[codes] => Array
(
[0] => XTAR
)
[max_people] => 4
[min_people] => 4
[max_bags] => 2
[min_bags] => 2
[price] => 307.64
)
)
You can do this with one call to usort
. 只需调用
usort
即可完成此操作。
First of all, you can also use array_flip
to make it easier to manage the $order
array. 首先,还可以使用
array_flip
来array_flip
$order
数组的管理。 That way you don't have to type (or change) the number values: 这样,您不必键入(或更改)数字值:
$order = array_flip([
'Economy Car',
'Compact Car',
'Mid-Size Car',
'Standard-Size Car',
'Full-Size Car',
'Premium Car',
'Luxury Car',
'Standard-Size Convertible',
'Mid-Size SUV',
'Standard SUV',
'Full-Size SUV',
'Minivan'
]);
And the sorting itself: 以及排序本身:
usort($car_types, function($a, $b) use ($order) {
$ret = (isset($order[$a->description]) ? $order[$a->description] : count($order))
- (isset($order[$b->description]) ? $order[$b->description] : count($order));
return $ret ? $ret : ($a->price - $b->price) * 100;
});
The first assignment calculates the difference in order based on the description field. 第一次分配根据描述字段按顺序计算差异。 If no order is known, a default value of
count($order)
is taken instead (using the ternary operator): this way car types that are not in the $order
array will be ordered after any car types that have an entry in $order
. 如果没有订单是已知的,默认值为
count($order)
取来代替(使用三元运算符):这路车的类型不属于在$order
排列将被责令后有一个条目的任何汽车类型$order
。 The count
function works here assuming you have numbered the types starting with 0 (which is the case with array_flip
), but you can use any great enough number instead. 假设您已经对以0开头的类型进行了编号(
array_flip
就是这种情况),那么count
函数在这里起作用,但是您可以使用任何足够大的数字来代替。
The return
statement then checks if the above value is different from zero, and if so returns it. 然后,
return
语句检查上面的值是否不同于零,如果是,则返回零。 If it is zero the difference in price (in cents) is returned. 如果为零,则返回价格差(以美分为单位)。 The value in cents is taken because the return value is expected to be an integer, not a float.
采用美分值,因为期望返回值是整数,而不是浮点数。 As said in the documentation :
如文档中所述:
Caution: Returning non-integer values from the comparison function, such as float, will result in an internal cast to integer of the callback's return value.
警告:从比较函数返回非整数值(例如float)将导致内部转换为回调返回值的整数。 So values such as 0.99 and 0.1 will both be cast to an integer value of 0, which will compare such values as equal.
因此,诸如0.99和0.1的值都将强制转换为整数值0,这会将这些值进行比较。
So just assign anything not in $order
the maximum sorting weight, and then add a secondary price comparison if the cars have identical weights. 因此,只要分配未按
$order
排序的最大排序权重,然后在汽车具有相同权重的情况下添加二级价格比较。 This method is far more simple and only requires one sort operation. 此方法简单得多,只需要一种排序操作。
usort($car_types, function($a, $b) use ($order) {
$a_weight = key_exists($a->description, $order) ? $order[$a->description] : PHP_INT_MAX;
$b_weight = key_exists($b->description, $order) ? $order[$b->description] : PHP_INT_MAX;
if( $a_weight != $b_weight ) {
return $a_weight - $b_weight;
} else {
return ( $a->price - $b->price ) * 100;
}
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.