简体   繁体   English

按自定义顺序(PHP)对Std类对象的数组进行排序

[英]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: 数组应按以下顺序排序:

  • Economy Car 经济车
  • Compact Car 小型车
  • Mid-Size Car 中型车
  • Standard-Size Car 标准尺寸车
  • Full-Size Car 全尺寸车
  • Premium Car 高档车
  • Luxury Car 豪华车
  • Standard-Size Convertible 标准尺寸敞篷车
  • Mid-Size SUV 中型SUV
  • Standard-Size SUV 标准尺寸SUV
  • Full-Size SUV 全尺寸SUV
  • Minivan 面包车
  • The remaining cars in the array should then be sorted by lowest to highest price (Example: After Minivan, display Specialty Vehicle, Compact SUV, Full-Size Hybrid, Sports, and so on...). 然后,应按最低到最高价格对阵列中的其余汽车进行排序(例如:在小型货车之后,展示特种车辆,紧凑型SUV,全尺寸混合动力车,运动型等等)。

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_fliparray_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM