【问题标题】:Sort an array of associative arrays by multiple columns using a combination of ascending, descending, regular, numeric, and natural sorting使用升序、降序、常规、数字和自然排序的组合按多列对关联数组的数组进行排序
【发布时间】:2011-10-20 16:35:58
【问题描述】:

是否可以在 PHP 中使用自然排序按多列对多维数组进行排序?这是一个例子。假设我有一个二维数据数组,例如,

$array[1]['Name'] = 'John';
$array[1]['Age'] = '20';
$array[1]['Code'] = 'ABC 12';

$array[2]['Name'] = 'John';
$array[2]['Age'] = '21';
$array[2]['Code'] = 'ABC 1';

$array[3]['Name'] = 'Mary';
$array[3]['Age'] = '20';
$array[3]['Code'] = 'ABC 10';

我想按名称(ASC)对这个数组进行排序,然后按年龄(DESC)和代码(ASC),所有这些都会自然排序。基本上这将是带有自然排序的array_multisort。

我在网上找到了很多关于这个主题的解决方案。不幸的是,它们只支持按一列排序,不支持多列。

【问题讨论】:

    标签: php arrays sorting natural-sort


    【解决方案1】:

    我认为您必须为此行为实现自定义比较功能:

    function myCmp($a, $b) {
     $nameCmp = strnatcasecmp($a['Name'], $b['Name']);
     $ageCmp = strnatcasecmp($a['Age'], $b['Age']);
     $codeCmp = strnatcasecmp($a['Code'], $b['Code']);
    
     if ($nameCmp != 0) // Names are not equal
       return($nameCmp);
    
     // Names are equal, let's compare age
    
     if ($ageCmp != 0) // Age is not equal
       return($ageCmp * -1); // Invert it since you want DESC
    
     // Ages are equal, we don't need to compare code, just return the comparison result
       return($codeCmp);
    }
    

    然后你可以调用usort($array, 'myCmp'); 并且应该得到想要的排序

    【讨论】:

      【解决方案2】:

      如果您使用的是 PHP 5.4 或更新版本,您可以使用 array_multisortSORT_NATURAL 标志。

      【讨论】:

        【解决方案3】:

        三个排序规则中只有一个实际上需要自然排序。事实上,如果你使用 PHP 的 3 路比较运算符(<=>),那么它会自动将数字字符串作为数值进行比较。只有第三条规则需要显式声明自然排序,因为它需要比较字母数字字符串。

        代码:(Demo)

        $array = [
            1 => ['Name' => 'John', 'Age' => '20', 'Code' => 'ABC 12'],
            2 => ['Name' => 'John', 'Age' => '21', 'Code' => 'ABC 1'],
            3 => ['Name' => 'Mary', 'Age' => '20', 'Code' => 'ABC 10'],
            4 => ['Name' => 'John', 'Age' => '20', 'Code' => 'ABC 1'],
            5 => ['Name' => 'John', 'Age' => '20', 'Code' => 'ABC 100'],
            6 => ['Name' => 'John', 'Age' => '20', 'Code' => 'ABC 2'],
        
        ];
        
        uasort(
            $array,
            fn($a, $b) =>
                [$a['Name'], $b['Age']] <=> [$b['Name'], $a['Age']] // name (ASC) then by age (DESC)
                ?: strnatcasecmp($a['Code'], $b['Code']) // then by code (ASC / naturally)
        );
        var_export($array);
        

        输出:

        array (
          2 => 
          array (
            'Name' => 'John',
            'Age' => '21',
            'Code' => 'ABC 1',
          ),
          4 => 
          array (
            'Name' => 'John',
            'Age' => '20',
            'Code' => 'ABC 1',
          ),
          6 => 
          array (
            'Name' => 'John',
            'Age' => '20',
            'Code' => 'ABC 2',
          ),
          1 => 
          array (
            'Name' => 'John',
            'Age' => '20',
            'Code' => 'ABC 12',
          ),
          5 => 
          array (
            'Name' => 'John',
            'Age' => '20',
            'Code' => 'ABC 100',
          ),
          3 => 
          array (
            'Name' => 'Mary',
            'Age' => '20',
            'Code' => 'ABC 10',
          ),
        )
        

        请注意,由于使用了uasort(),所以输出中保留了第一级键。因为输入数组没有被索引,所以我假设键是 id 或其他重要的东西。


        如果您对重新索引父级键感到满意,则可以在生成列数据数组后使用array_multisort()。 (Demo)

        foreach ($array as ['Name' => $names[], 'Age' => $ages[], 'Code' => $codes[]]);
        
        array_multisort(
            $names,        // ASC, REGULAR
            $ages,         // DESC, NUMERIC
            SORT_DESC,
            SORT_NUMERIC,
            $codes,        // ASC, NATURAL
            SORT_ASC,
            SORT_NATURAL,
            $array         // the array to be affected
        );
        var_export($array);
        

        【讨论】:

          猜你喜欢
          • 2015-08-30
          • 1970-01-01
          • 1970-01-01
          • 2021-12-28
          • 1970-01-01
          • 1970-01-01
          • 2014-02-16
          • 2018-10-26
          • 1970-01-01
          相关资源
          最近更新 更多