基于数字值对数组进行排序,但如果是布尔值,则添加到结尾

时间:2015-06-05 13:59:14

标签: php arrays sorting

我有一个多维数组,我想根据距离值进行排序,其中假值应该添加到它们之前关于数组的位置的末尾。

$things.query({},{'client_id':'1'}).$promise.then(function(result){
    $scope.thing = result;
    console.log($scope.thing);
});

我想对此进行排序:

$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 

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

5 个答案:

答案 0 :(得分:0)

PHP的排序功能不是'stable'。因此,如果比较函数返回0,则无法预测结果的顺序。您必须编写自己的函数,如here所示。

答案 1 :(得分: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);

答案 2 :(得分: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);

答案 3 :(得分:0)

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

代码:

ul - each user in users 
li #{user.username}

排序数组位于变量$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值;
  • on tie,使用false;
  • 的值

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

因为字符串是使用字典顺序排序的,所以distancedistance替换为false)的值被格式化为固定长度的字符串(20个字符,6个它们是小数),用999999左边填充。

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

0

对于sprintf('%020.6f/%s', $item['distance'] === false ? 999999 : $item['distance'], $item['name']), ); ,上面的sprintf()会生成:

Array 1

答案 4 :(得分:0)

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