如何按特定列值的前导整数对子数组排序


How to sort a subarrays by the leading integers of a specific column value?

下面的数组按cat_url_title的第一个数字从小到大排序。

Array
(
    [0] => Array
        (
            [cat_id] => 14
            [parent_id] => 2
            [cat_url_title] => 20-a-43m
        )
    [1] => Array
        (
            [cat_id] => 13
            [parent_id] => 2
            [cat_url_title] => 16-a-20m            
        )
    [2] => Array
        (
            [cat_id] => 12
            [parent_id] => 2
            cat_url_title] => 12-a-16m
        )
)
//get the first number
foreach( $arr as $k => $v )
{
    $segs = explode("-",$v['cat_url_title']);
    $nbr = $segs[0]; //this will be 20, 16 or 12
} 

cat_url_title值从12开始的子数组应该变为$arr[0], 16应该保持为$arr[1], 20应该移动到$arr[2]

我怎样才能做到这一点?

你是在一个很好的方式,获得第一个数字后,创建一个新的数组,其中包含数字作为键和数组的内容作为值:

$newArray = array();
foreach($arr as $k => $v)
{
  $segs = explode("-", $v['cat_url_title']);
  $newArray[ $segs[0] ] = $v;
}
ksort($newArray);
print_r($newArray);

usort()

参见usort() php函数

关于php中数组排序函数的有趣页面:http://us.php.net/manual/en/array.sorting.php

一行:

array_multisort(array_map('end', $array), SORT_NUMERIC, $array);

假设 :

$array = array (
    0 => array (
        'cat_id' => 14,
        'parent_id' => 2,
        'cat_url_title' => '20-a-43m'
    ),
    1 => array (
        'cat_id' => 13,
        'parent_id' => 2,
        'cat_url_title' => '16-a-20m'
    ),
    2 => array (
        'cat_id' => 12,
        'parent_id' => 2,
        'cat_url_title' => '12-a-16m'
    )
);

下面是我用来排序数组的函数:

function array_sort($array, $on, $order='SORT_DESC' /*or SORT_ASC*/ )
    {
      $new_array = array();
      $sortable_array = array();
      if (count($array) > 0) {
          foreach ($array as $k => $v) {
              if (is_array($v)) {
                  foreach ($v as $k2 => $v2) {
                      if ($k2 == $on) {
                          $sortable_array[$k] = $v2;
                      }
                  }
              } else {
                  $sortable_array[$k] = $v;
              }
          }
          switch($order)
          {
              case 'SORT_ASC':   
                  asort($sortable_array);
              break;
              case 'SORT_DESC':
                  arsort($sortable_array);
              break;
          }
          foreach($sortable_array as $k => $v) {
              $new_array[] = $array[$k];
          }
      }
      return $new_array;
    } 

用法:

array_sort($restaurants_top, "score", 'SORT_DESC');

$restaurants_top =一个餐馆列表"score" =一个数组键SORT_DESC =排序方向

Tomasz建议的array_multisort()是一种聪明的、声明性的、简洁的技术,在php版本中已经使用了很多年。如果这个任务在我的项目中,我可能会使用array_multisort()

我可能会建议,为了项目的稳定性(如果数据结构被扩展/更改),显式地命名要排序的列。下面的代码片段也避免了进行迭代的end()调用。

array_multisort(array_column($array, 'cat_url_title'), SORT_NUMERIC, $array);

作为学术练习,我将展示几个现代的替代方案。

从PHP7开始,太空船操作符也提供了简洁的语法。将第一个连字符之前的数字子字符串隔离为整数。

usort($array, function($a, $b) {
    return (int)$a['cat_url_title'] <=> (int)$b['cat_url_title'];
});

从PHP7.4开始,箭头函数语法使usort()调用更简洁,但如果您不习惯这种语法,则可能更难以理解。

usort($array, fn($a, $b) => (int)$a['cat_url_title'] <=> (int)$b['cat_url_title']);

与我几乎所有的php帖子一样,这里有一个在线演示来证明我所有的代码片段都能正常工作。

应该避免本页中多次迭代输入数组的代码片段。


注。如果您希望对四个数字/字母子字符串上的cat_url_title值进行排序,您可以将这些子字符串写为太空船操作符两侧的数组,它将从左到右计算子字符串以确定排序结果。

代码(演示):

usort($array, function($a, $b) {
    return (preg_match_all('~[a-z]+|'d+~', $a['cat_url_title'], $out) ? $out[0] : ['','','',''])
           <=> 
           (preg_match_all('~[a-z]+|'d+~', $b['cat_url_title'], $out) ? $out[0] : ['','','','']);
});

最大功率。这对version_compare()来说可能是一个很好的例子。不幸的是,它是不可靠的字符串在我的测试电池。注意这个演示中16-a-20n子数组的最终位置。我认为函数忽略了最后一个字母,因为在16-a-20m16-a-20n之间的求值是0

对于具有一致的am子字符串位置的示例字符串,它可以完美地自然排序。

代码(演示):

usort($array, function($a, $b) {
    return version_compare($a['cat_url_title'], $b['cat_url_title']);
});