根据数值对数组进行排序,但如果是布尔值,则添加到末尾

问题描述 投票:0回答:6

我有一个多维数组,我想根据距离值进行排序,其中应将错误值添加到其数组之前位置的末尾。

$array = array(
        array('name' => 'Array 1', 'distance' => 3.4),
        array('name' => 'Array 2', 'distance' => 2.4),
        array('name' => 'Array 3', 'distance' => false),
        array('name' => 'Array 4', 'distance' => 5.4),
        array('name' => 'Array 5', 'distance' => false),
        array('name' => 'Array 6', 'distance' => 1),
        array('name' => 'Array 7', 'distance' => false),
        array('name' => 'Array 8', 'distance' => false),
        array('name' => 'Array 9', 'distance' => 3.6),
    );

我想将其排序为:

Array 6 1
Array 2 2.4
Array 1 3.4
Array 9 3.6
Array 4 5.4
Array 3 
Array 5 
Array 7 
Array 8 

我只能做到这一点:

Array 6 1
Array 2 2.4
Array 1 3.4
Array 9 3.6
Array 4 5.4
Array 8 
Array 5 
Array 3 
Array 7 

我的尝试:

usort($array, function($a, $b){
    if(!$b['distance'])
        return -1;
    elseif(!$a['distance'])
        return 1;

    return $a['distance'] - $b['distance'];
});

编辑:添加我的解决方案作为答案

php arrays sorting
6个回答
1
投票
// Filter items with NULL in distance
$withoutDistance = array_filter($array, function($item) { return !$item["distance"];});
// Take the rest 
$withDistance = array_diff_assoc($array, $withoutDistance);
// Sort by distance
usort($withDistance, function($a, $b){ 
      if ( $a['distance'] == $b['distance']) return 0;;
      return $a['distance'] > $b['distance'] ? 1: -1; });
// Return NULL distance into array
$array = array_merge($withDistance, $withoutDistance);

0
投票

PHP 的排序函数不是 ‘稳定’。因此,如果比较函数返回 0,您无法预测结果的顺序。您必须编写自己的函数,如here所示。


0
投票

这似乎完全符合您的要求,但请记住 array_reverse!。

usort($array, function($a, $b){

    $isBFalse = is_bool($b['distance']) && $b['distance'] == false;
    $isAFalse = is_bool($a['distance']) && $a['distance'] == false;

    if($isBFalse && $isAFalse){
        return 0;
    }else if($isBFalse){
        return 1;
    }
    else if($isAFalse){
        return -1;
    }

    return $a['distance'] - $b['distance'];
});

$array = array_reverse($array);

0
投票

分两步对数组进行排序的解决方案。第一步为每个元素计算一个排序键并将其存储在元素本身中。第二步使用第一步创建的排序键的简单字符串比较来进行实际排序。

代码:

$new = array_map(
    function (array $item) {
        return array(
            'name'     => $item['name'],
            'distance' => $item['distance'],
            'sort_key' => sprintf('%020.6f/%s',
                    $item['distance'] === false ? 999999 : $item['distance'],
                    $item['name']),
        );
    },
    $array
);

usort(
    $new,
    function (array $a, array $b) {
        return strcmp($a['sort_key'], $b['sort_key']);
    }
);

排序后的数组位于变量

$new
中,原始数组
$array
不受影响。

如何运作

第一步生成一个新数组。数组中的每个条目都包含来自

$array
的原始条目以及名为
sort_key
的额外属性。

sort_key
的值是一个用于排序的字符串。排序标准是:

  • 比较
    distance
    的值并将
    false
    放在最后;这意味着
    false
    大于任何非
    false
    值;
  • 在领带上,使用
    name
    的值;

为了将

false
排序为大于任何非
false
distance
,请将
false
替换为一个大数字。上面的代码使用了
999999
。调整此值以确保它比任何值都大
distance

因为字符串是使用字典顺序排序的,所以

distance
的值(将
false
替换为
999999
)被格式化为固定长度字符串(20个字符,其中6个是小数),左填充与
0

名称附加到该字符串后;它已经是字符串,不需要任何其他处理。

sprintf('%020.6f/%s',
           $item['distance'] === false ? 999999 : $item['distance'],
           $item['name']),
);

对于

Array 1
,上面的
sprintf()
生成:

0000000000003.400000/Array 1

0
投票
$withDistance = array();
$withoutDistance = array_filter($array, function($array) use (&$withDistance) {
    if($array['distance'] !== false) {
        $withDistance[] = $array;
        return false;
    }
    return true;
});

usort($withDistance, function($a, $b){
    if ($a['distance'] == $b['distance']) return 1;
    return $a['distance'] > $b['distance'] ? 1: -1;
});

$array = array_merge($withDistance, $withoutDistance);

0
投票

用宇宙飞船运算符和两条规则排序:

  1. 升序排序如果
    distance
    false
    ,则
  2. distance
    排序。

代码:(演示

usort(
    $array,
    fn($a, $b) => [$a['distance'] === false, $a['distance']]
                  <=>
                  [$b['distance'] === false, $b['distance']]
);
var_export($array);
© www.soinside.com 2019 - 2024. All rights reserved.