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

时间:2017-09-05 19:58:57

标签: php arrays sorting multidimensional-array stdclass

我有一组StdClass对象,包含不同的车型(例如紧凑型车,中型车等)。应按以下顺序对数组进行排序:

  • 经济型轿车
  • 紧凑型车
  • 中型车
  • 标准尺寸车
  • 全尺寸车
  • Premium Car
  • 豪华车
  • 标准尺寸敞篷车
  • 中型SUV
  • 标准尺寸SUV
  • 全尺寸SUV
  • 面包车
  • 阵列中的其余车辆应按最低价格到最高价格进行分类(例如:小型货车后,展示专用车辆,紧凑型SUV,全尺寸混合动力,运动等......)。 /强>

我遇到了按价格对剩余车辆进行分类的问题。我尝试先按价格排序,然后按第二次排序中的有序列表排序,但它没有按预期工作。任何帮助,将不胜感激。我之前发布了一个类似的问题,但我想我会重新发布一个更有条理的需求版本。

输入数组:

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',
  )),
)

代码:

    $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;
    });

新输出:

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
    )
)

2 个答案:

答案 0 :(得分:1)

您可以通过拨打usort来完成此操作。

首先,您还可以使用array_flip来更轻松地管理$order数组。这样您就不必输入(或更改)数字值:

$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'
]);

排序本身:

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;
});

第一个作业根据 description 字段按顺序计算差异。如果未知订单,则取代默认值count($order)(使用三元运算符):这样,在任何具有“{1}”数组的车型之后,将排序不在$order数组中的汽车类型$order中的条目。 count函数在这里工作,假设您已经编号从0开始的类型(array_flip的情况),但您可以使用任何足够多的数字。

return语句然后检查上面的值是否与零不同,如果是,则返回它。如果为零,则返回价格差异(以美分计)。以美分为单位的值是因为返回值预期是整数,而不是浮点数。如documentation中所述:

  

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

答案 1 :(得分:0)

因此,只需在$order中分配 中的任何最大排序权重,然后在汽车具有相同权重时添加二级价格比较。这种方法要简单得多,只需要一个排序操作。

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;
    }
});