【问题标题】:usort multisort array based on another array基于另一个数组的排序多排序数组
【发布时间】:2014-10-25 12:48:24
【问题描述】:

我有一个数组,我需要按另一个数组排序,形成 2 个字段的邮政编码并批准

我可以按邮政编码对其进行排序,但无法使用已批准的字段进行排序,例如

我需要按 60007,60001,60003,60002 排序 (按照排序顺序) 所有来自 60007 并获得批准的邮政编码都应该排在第一位,所以

$sortLike=array(60007,60001,60003,60002);
$array1= array(
    array ('ID' => 138,'zip_code' => 60007,'approved' => 1),
    array('ID' => 103,'zip_code' => 60007,'approved' => 0),
    array('ID' => 114,'zip_code' => 60007,'approved' => 1),
    array('ID' => 105,'zip_code' => 60003,'approved' => 0),
    array('ID' => 124,'zip_code' => 60002,'approved' => 0)
)

所以 60007 和 aproved 应该比 60007 和 0(未批准)和所有 60001 批准比所有 60001 未批准(依此类推$sortlike)这里是完整的 php 代码

<?php
$array1= array(
    array ('ID' => 138,'zip_code' => 60007,'approved' => 1),
    array('ID' => 103,'zip_code' => 60007,'approved' => 0),
    array('ID' => 114,'zip_code' => 60007,'approved' => 1),
    array('ID' => 105,'zip_code' => 60003,'approved' => 0),
    array('ID' => 124,'zip_code' => 60002,'approved' => 0),
    array('ID' => 104,'zip_code' => 60002,'approved' => 1),
    array('ID' => 106,'zip_code' => 60001,'approved' => 0),
    array('ID' => 188,'zip_code' => 60022,'approved' => 0),
    array('ID' => 184,'zip_code' => 60022,'approved' => 1),
);
function sort_results ($a, $b) {
   $sortLike=array(60007,60001,60003,60002);
   if (!in_array ($a['zip_code'], $sortLike)) { return 1; } // Push unknown values at the end of the array
   return array_search($a['zip_code'], $sortLike) > array_search($b['zip_code'], $sortLike);
}

usort ($array1, 'sort_results');
echo "<pre>";
print_r($array1);
echo "</pre>";

【问题讨论】:

    标签: php arrays sorting multidimensional-array usort


    【解决方案1】:

    usort()PHP Demo)

    $priorityZips = array_flip([60007, 60001, 60003, 60002]);
    $priorityCount = count($priorityZips);
    
    usort($rows, function($a, $b) use ($priorityZips, $priorityCount) {
        return [
                   $priorityZips[$a['zip_code']] ?? $priorityCount,
                   $a['zip_code'],
                   $b['approved']
               ]
               <=>
               [
                   $priorityZips[$b['zip_code']] ?? $priorityCount,
                   $b['zip_code'],
                   $a['approved']
               ];
    });
    

    usort() PHP >= v7.4: (Demo)

    $priorityZips = array_flip([60007, 60001, 60003, 60002]);
    $priorityCount = count($priorityZips);
    
    usort($rows, fn($a, $b) =>
        [
            $priorityZips[$a['zip_code']] ?? $priorityCount,
            $a['zip_code'],
            $b['approved']
        ]
        <=>
        [
            $priorityZips[$b['zip_code']] ?? $priorityCount,
            $b['zip_code'],
            $a['approved']
        ]
    );
    

    array_multisort()PHP Demo)

    $priorityZips = array_flip([60007, 60001, 60003, 60002]);
    $priorityCount = count($priorityZips);
    
    array_multisort(
        array_map(
            function($row) use ($priorityZips, $priorityCount) {
                return $priorityZips[$row['zip_code']] ?? $priorityCount;
            },
            $rows
        ),
        array_column($rows, 'zip_code'),
        array_column($rows, 'approved'),
        SORT_DESC,
        $rows
    );
    

    array_multisort() PHP >= v7.4: (Demo)

    $priorityZips = array_flip([60007, 60001, 60003, 60002]);
    $priorityCount = count($priorityZips);
    
    array_multisort(
        array_map(
            fn($row) => $priorityZips[$row['zip_code']] ?? $priorityCount,
            $rows
        ),
        array_column($rows, 'zip_code'),
        array_column($rows, 'approved'),
        SORT_DESC,
        $rows
    );
    

    在我上面的 sn-ps 中,我指的是你的输入数组被排序为$rows

    可以通过多种方式执行此任务,但我展示了一些我认为最干净/最易读的方法。如果性能对您的应用程序至关重要,我鼓励您使用自己的真实数据进行基准测试;否则请选择您最适合长期维护的 sn-p。

    在低于 7.4 的 PHP 版本中,将变量传递到自定义函数作用域是使用 use() 完成的。在 PHP7.4 及更高版本中,“arrow function syntax”在自定义函数中去掉了相当多的语法块,并允许在没有use() 的情况下输入变量。

    spaceship operator”/“三向比较运算符”(&lt;=&gt;) 使得构建多标准排序与一堆条件块相比更加简洁明了。 spaceship 运算符将同步处理数组中的元素并返回正确评估的-101。它还将数字字符串视为数字。

    我翻转了优先邮政编码的查找数组,以使“null coalescing operator”(??) 能够快速返回优先级值,否则默认为大于查找中最高整数值的数字。

    关于被比较的 usort 数组的结构,您可能希望看到更详细的 this answer

    【讨论】:

      【解决方案2】:

      我猜您是在问如何也可以按 'approved' 排序,因为您的代码中目前没有。

      这个问题的解决方案是定义检查输入数组$array1 的键的顺序。

      所以你首先需要检查zip_code。如果你得到一个结果!= 0,你可以立即返回。但如果结果是 == 0(邮政编码相等),则需要检查第二个键(在您的情况下为 'approved')。

      $array1= array(
          array ('ID' => 138,'zip_code' => 60007,'approved' => 1),
          array('ID' => 103,'zip_code' => 60007,'approved' => 0),
          array('ID' => 114,'zip_code' => 60007,'approved' => 1),
          array('ID' => 105,'zip_code' => 60003,'approved' => 0),
          array('ID' => 124,'zip_code' => 60002,'approved' => 0),
          array('ID' => 104,'zip_code' => 60002,'approved' => 1),
          array('ID' => 106,'zip_code' => 60001,'approved' => 0),
          array('ID' => 188,'zip_code' => 60022,'approved' => 0),
          array('ID' => 184,'zip_code' => 60022,'approved' => 1),
      );
      function sort_results ($a, $b) {
          $sortLike=array(60007,60001,60003,60002);
          if (!in_array ($a['zip_code'], $sortLike)) { return 1; } // Push unknown values at the end of the array
          $zip_res = array_search($a['zip_code'], $sortLike) - array_search($b['zip_code'], $sortLike); // check zip_code order 
          if($zip_res == 0){ // if the zip_codes are equal
              $zip_res = $b['approved'] - $a['approved']; // sort by the 'approved' key
          }
          return $zip_res;
      }
      

      //编辑

      您可以使用 lamda 函数将$sortLike 移出函数(需要 PHP >= 5.3):

      $sortLike=array(60007,60001,60003,60002);
      $sort_results = function ($a, $b) use ($sortLike){ // create lambda function with "use" keyword
          if (!in_array ($a['zip_code'], $sortLike)) { return 1; } // Push unknown values at the end of the array
          $zip_res = array_search($a['zip_code'], $sortLike) - array_search($b['zip_code'], $sortLike);
          if($zip_res == 0){
              $zip_res = $b['approved'] - $a['approved'];
          }
          return $zip_res;
      };
      
      usort ($array1,$sort_results); // pass lambda function in
      echo "<pre>";
      print_r($array1);
      echo "</pre>";
      die();
      

      【讨论】:

      • 这是我需要的,与其他解决方案相比似乎非常快,你能帮忙把 $sortLike 放在 sort_results 之外,因为 sort_result 是一个来自数据库的数组,所以 $sortLike 必须作为调用 usort 的参数
      • 当然,您可以使用anonymous function 轻松做到这一点。我更新了答案以包含相应的代码。如果它解决了您的问题,请随时接受答案;)
      【解决方案3】:
      usort($array_data, array($sort_obj = new cmpArray('array_key'), "cmp__"));
      class cmpArray
           {
      
               var $key;
      
               function __construct($key)
               {
                   $this->key = $key;
               }
      
               function cmp__($a, $b)
               {
                   $key = $this->key;
                   if($a[$key] == $b[$key])
                       return 0;
      
                   return (($a[$key] > $b[$key]) ? 1 : -1);
               }
      
           }
      

      【讨论】:

      • 在 array_key 的地方写下你想要对数组进行排序的数组键
      • 我希望对 2 个数组元素 1) 邮政编码 2) 批准的字段进行排序
      【解决方案4】:
      <?php
      $array1= array(
      array ('ID' => 138,'zip_code' => 60007,'approved' => 1),
      array('ID' => 103,'zip_code' => 60007,'approved' => 0),
      array('ID' => 114,'zip_code' => 60007,'approved' => 1),
      array('ID' => 105,'zip_code' => 60003,'approved' => 0),
      array('ID' => 124,'zip_code' => 60002,'approved' => 0),
      array('ID' => 104,'zip_code' => 60002,'approved' => 1),
      array('ID' => 106,'zip_code' => 60001,'approved' => 0),
      array('ID' => 188,'zip_code' => 60022,'approved' => 0),
      array('ID' => 184,'zip_code' => 60022,'approved' => 1),
      );
      
      function sort_it ($a) {
      $sortedarr = array();
      $sortLike=array(60007,60001,60003,60002);
      foreach($sortLike as $el){
          array_push($sortedarr,getElements($a,$el));
      }
      }
      
      
      
      function getElements($arr,$e){
      $newarr = array();
      foreach($arr as $val){
          if($val['approved'] == '1' && $val['zip_code'] == $e){
          $newarr[] = $val;
          }
      }
      foreach($arr as $val){
          if($val['approved'] == '0' && $val['zip_code'] == $e){
          $newarr[] = $val;
          }
      }
      return $newarr;
      }
      
      $array2 = sort_it($array1);
      echo "<pre>";
      print_r($array1);
      echo "</pre>";
      echo "<pre>";
      print_r($array2);
      echo "</pre>";
      ?>
      

      【讨论】:

        猜你喜欢
        • 2021-07-17
        • 2013-06-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-25
        相关资源
        最近更新 更多