【问题标题】:Sort data in array with special key使用特殊键对数组中的数据进行排序
【发布时间】:2019-08-26 09:36:33
【问题描述】:

如果键不仅仅是字符串(乍一看),如何对数组中的数据进行排序,而是包含由字符“_”分隔的数字

f.e.:

id_1_2_-1.25_0
id_1_2_-0.25_0
id_1_2_1.75_0
id_1_2_3_0
id_1_2_-4_0
id_1_2_0_0

ksort()不能使用,因为像-1.25这样的值前面的“减号”符号不被识别为负数,而是作为特殊符号

重要!!我不能只分隔一个数字(-1.25、-0.25、1.75、3、-4、0),其他数字也可能不同,例如id_9_4_-2.25_1,并且数组按字符“_” f.e. 之间的所有数字排序。首先是9,然后是4,然后是-2.25,最后一个是1

我需要结果(排序键):

id_1_2_-4_0
id_1_2_-1.25_0
id_1_2_-0.25_0
id_1_2_0_0
id_1_2_1.75_0
id_1_2_3_0

【问题讨论】:

    标签: php arrays sorting


    【解决方案1】:

    spaceship 运算符对数组进行排序没有问题。每次只需炸开钥匙即可。

    代码:(Demo)

    $indexes = [
        'id_1_2_3_0' => 1,
        'id_1_2_-0.25_0' => 2,
        'id_1_2_1.75_0' => 3,
        'id_1_2_-4_0' => 4,
        'id_1_2_0_0' => 5,
        'id_1_2_-1.25_0' => 6,
    ];
    
    uksort($indexes, function($a, $b) {
        return explode('_', $a) <=> explode('_', $b);
    });
    
    var_export($indexes);
    

    从 PHP7.4 开始,您可以使用更简洁的箭头函数语法。 (Demo)

    uksort($indexes, fn($a, $b) => explode('_', $a) <=> explode('_', $b));
    

    附言如果你真的想激怒你的代码的未来读者,你可以爆炸每个键,转置(旋转 90 度)生成的列数据,然后调用array_multisort()。 (Demo)

    [$c1, $c2, $c3, $c4, $c5] = array_map(null, ...array_map(fn($k) => explode('_', $k), array_keys($indexes)));
    array_multisort($c1, $c2, $c3, $c4, $c5, $indexes);
    

    【讨论】:

    • 比我预期的要容易 - 你比 @Claudio 干净得多,但两者都在工作,所以谢谢
    • @mickmackusa +1 for 7.4 语法:)
    • @splash ...是的,干杯,现在它可用了,我正试图将它挤进我所有的新答案中。
    【解决方案2】:

    您可以使用ksort 函数来指定数组,并指定一个回调函数,使用spaceship 运算符单独比较每个值,如下所示:

    $indexes = [
        'id_1_2_3_0' => 1,
        'id_1_2_-0.25_0' => 1,
        'id_1_2_1.75_0' => 1,
        'id_1_2_-4_0' => 1,
        'id_1_2_0_0' => 1,
        'id_1_2_-1.25_0' => 1,
    ];
    
    uksort($indexes, function($current, $next) {
        // break the strings to compare the values individually (str_replace is used to remove the 'id_' from the key)
        $currentParts = explode('_', str_replace('id_', '', $current));
        $nextParts = explode('_', str_replace('id_', '', $next));
    
        foreach ($currentParts as $i => $part) {
            // edge case when the indexes have different lengths (can be removed if the keys always have the same length)
            if (!isset($nextParts[$i])) {
                return 0; // the strings don't have the same length
            }
    
            $comparisonResult = $part <=> $nextParts[$i];
    
            // if the values are different, the comparison result is returned
            if ($comparisonResult !== 0) {
                return $comparisonResult;
            }
        }
    
        // reaching this return means the keys being compared are equal
        return 0;
    });
    

    结果是(PHPSandbox):

    Array
    (
        [id_1_2_-4_0] => 1
        [id_1_2_-1.25_0] => 1
        [id_1_2_-0.25_0] => 1
        [id_1_2_0_0] => 1
        [id_1_2_1.75_0] => 1
        [id_1_2_3_0] => 1
    )
    

    【讨论】:

      【解决方案3】:

      我觉得可能是这样的

      function getValue($raw) {
          $value = explode('_', $raw);
      
          return $value[count($value) - 2];
      }
      
      uksort($a, function ($a, $b) {
          $aKey = (float) getValue($a);
          $bKey = (float) getValue($b);
      
          return $aKey <=> $bKey;
      });
      

      【讨论】:

      • 这个按数字排序的数组 [-1.25, -0.25, 1.75, 3, -4, 0],我在你写这个的时候编辑过,我写的数组必须按 a 之间的所有数字排序字符“_”,没关系:) ..同时有人写了我需要的函数。但是感谢您的宝贵时间。
      猜你喜欢
      • 1970-01-01
      • 2011-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-18
      • 2011-04-05
      • 2018-03-12
      相关资源
      最近更新 更多