php 使用array_multisort()自定义排序多维数组

bkhjykvo  于 2023-01-24  发布在  PHP
关注(0)|答案(2)|浏览(125)

我有以下数组:

$array = [
    'note' => [],
    'year' => ['2011','2010', '2012'],
    'type' => ['conference', 'journal', 'conference'],
];

我使用下面的函数,通过字段类型和另一个数组对数组进行排序:

function array_multisort_by_order(array $array, $by, array $order)
{
    $order = array_flip($order);
    $params[] = $array[$by];
    foreach($params[0] as &$v) $v = $order[$v];
    foreach($array as &$v) $params[] = &$v; unset($v);
    call_user_func_array('array_multisort', $params);
    return $array;
}

当我调用下面的函数时,我得到了下面的错误:

$array = array_multisort_by_order($array, 'type', array('conference', 'journal'));

print_r($array['type']);

错误:

Warning: array_multisort(): Array sizes are inconsistent.

我知道数组是不一致的,有没有更好的函数?
请检查:codepad
预期输出:

Array
(
[note] => Array
    (
        [0] => 
        [1] => 
        [2] => 
    )

[year] => Array
    (
        [0] => 2011
        [1] => 2012
        [2] => 2010
    )

[type] => Array
    (
        [0] => conference
        [1] => conference
        [2] => journal
    )

)

例二:

    • 阵列**
$array = [
    'note' => ['test1', 'test2'],
    'year' => ['2011', '2012'],
    'type' => ['conference', 'journal', 'conference'],
];
    • 预期结果2**
Array
(
[note] => Array
    (
        [0] => test1
        [1] => 
        [2] => tes2
    )

[year] => Array
    (
        [0] => 2011
        [1] => 2012
        [2] => 
    )

[type] => Array
    (
        [0] => conference
        [1] => conference
        [2] => journal
    )

)
2fjabf4q

2fjabf4q1#

好的,首先想到的解决方案之一就是添加空值,使它们一致:

function array_multisort_by_order(array $array, $by, array $order)
{
     $max = max(array_map('count',$array));
    //or, alternatively, depending on input (if there are no 'complete' subarrays):
    //$max = max(array_map(function($arr){return max(array_keys($arr));},$array))+1;

    //ADDITION: negative numeric keys:
    $min = min(array_map(function($arr){return min(array_keys($arr));},$array));
    $width = $max - min(0,$min);

    foreach($array as &$sub){
        // $addin = array_diff_key(array_fill(0,$max,null),$sub);
        // $addin changed for negative keys:
        $addin = array_diff_key(array_combine(range($min,$max),array_fill(0,$width,null)),$sub);
        $sub = $addin + $sub;
        ksort($sub);
    }
    $order = array_flip($order);
    $params[] = $array[$by];
    foreach($params[0] as &$v) $v = $order[$v];
    foreach($array as &$v) $params[] = &$v; unset($v);
    call_user_func_array('array_multisort', $params);
    //no closeures here:
    //foreach($array as &$sub) $sub = array_filter(function($a){return !is_null($a);},$sub);
    $filter = create_function('$a','return !is_null($a);');
    foreach($array as &$sub) $sub = array_filter($sub,$filter);
    return $array;
}
z9smfwbn

z9smfwbn2#

1.填充行以具有一致的元素计数。
1.使用自定义排序条件生成查找数组,然后使用这些转换值填充第一个排序参数。
1.将所有行作为引用变量压入排序参数的有效负载。
1.使用array_multisort()排序。不需要return,因为所有排序操作都通过引用完成。
代码:(Demo

function array_multisort_custom(array &$array, $columnKey, array $order)
{
    // guard clause/condition
    if (!array_key_exists($columnKey, $array)) {
        throw new Exception('Nominated sorting column not found');
    }
    
    // pad rows to consistent size
    $maxCount = max(array_map('count', $array));
    array_walk($array, fn(&$row) => $row = array_pad($row, $maxCount, null));

    // populate first sorting parameter with custom order array
    $priority = array_flip($order);
    $default = count($order);
    foreach ($array[$columnKey] as $v) {
        $params[0][] = $priority[$v] ?? $default;
    }
    
    // assign reference variables to parameter array for all rows
    foreach ($array as &$row) {
        $params[] = &$row;
    }
    
    array_multisort(...$params);
}

array_multisort_custom($array, 'type', ['conference', 'journal']);
var_export($array);

如果输入数组的第一级键是数字键,则可以进一步压缩上面的代码片段,并删除最后一个foreach()(因为可以使用array_multisort()中的spread操作符来解压缩数字键)、Demo甚至Demo
相关答案:Sort array using array_multisort() with dynamic number of arguments/parameters/rules/data

相关问题