将具有特定值的数组元素移动到数组的顶部


Move array element with a particular value to top of array

我有一个类似于这样的数组:

Array
(
  [0] => stdClass Object
    (
      [Leasing] => 12939.74
      [Name] => Jeremy
      [Rental] => 0
      [Sales] => 56603.13
      [Total] => 69542.87
    )
  [1] => stdClass Object
    (
      [Leasing] => 0
      [Name] => Shaun
      [Rental] => 0
      [Sales] => 58590
      [Total] => 58590
    )
  [2] => stdClass Object
    (
      [Leasing] => 0
      [Name] => Lindsay
      [Rental] => 0
      [Sales] => 22951.97
      [Total] => 22951.97
    )
  [3] => stdClass Object
    (
      [Leasing] => 0
      [Name] => Sally
      [Rental] => 1200
      [Sales] => 21624.9
      [Total] => 22824.9
    )
  [4] => stdClass Object
    (
      [Leasing] => 0
      [Name] => House
      [Rental] => 0
      [Sales] => 16235.81
      [Total] => 16235.81
    )
  [5] => stdClass Object
    (
      [Leasing] => 5298.85
      [Name] => Bill
      [Rental] => 1200
      [Sales] => 0
      [Total] => 6498.85
    )
)

目前,数组是按总数排序的:

usort($data, function ($a, $b) {
    return $b->Total - $a->Total;
});

现在,我需要能够始终拥有具有[Name] => House的人到数组的顶部。我的想法是,我可以让它按Total排序(因为我仍然需要这样),然后用House值取元素,并把它放在数组的开头。我可以选择一个特定的KEY并将其放在顶部,但KEY的变化可能取决于谁拥有最高的总数。我怎么能总是把名为House的人放在数组的顶部呢?

应该可以:

usort($data, function ($a, $b) {
    if ($a->Name != "House" && $b->Name == "House") {
        return 1;
    } elseif ($a->Name == "House" && $b->Name != "House") {
        return -1;
    } else {
        return $b->Total - $a->Total;
    }
});

From PHP: usort - Manual:

如果认为第一个参数分别小于、等于或大于第二个参数,比较函数必须返回小于、等于或大于零的整数。

在本例中,返回1告诉排序函数House大于任何其他值,-1告诉排序函数House小于任何其他值。

您的要求:

  1. Name列排序——将House值的行置于非House值的行之前。
  2. Total列DESC排序。

从PHP7开始,太空船操作符(<=>)通过计算规则数组(从左到右读取元素)使脚本的排序规则非常干净。

要首先对House行进行排序,计算每个对象的Name字符串使其与House相同。false评价将被视为0, true评价将被视为1。通过将$b数据写入操作符的左侧,实现降序排序。House对象将是唯一被计算为true的对象,因为它是第一个排序条件,它将作为对象数组中的第一个对象获得优先级。

对于不包含House的其他对象,计算第二个排序条件。通过将$bTotal值写在左侧,将$aTotal值写在右侧,再次使用降序排序——这将总数较高的对象放在总数较低的对象之前。

代码(演示):

usort(
    $objects,
    fn($a, $b) =>
         [$b->Name === 'House', $b->Total]
         <=>
         [$a->Name === 'House', $a->Total]
);

为了完整性,您也可以使用array_multisort(),但在这种情况下,它将比usort()效率低,因为需要多个函数调用来准备排序列。(演示)

array_multisort(
    array_map(fn($obj) => $obj->Name !== 'House', $objects), // ASC puts falses before trues
    array_column($objects, 'Total'),
    SORT_DESC,
    $objects
);