使用 array_multisort() 和动态数量的参数/参数/规则/数据对数组进行排序

问题描述 投票:0回答:6

我正在尝试使用

array_multisort()
对任何数组进行排序,一切都运行良好。但是,根据脚本中的条件,我需要更改选项。

到目前为止我所拥有的是:

array_multisort(
    $sort1,
    SORT_ASC,
    $sort2,
    SORT_ASC,
    $sort3,
    SORT_ASC, 
    $arraytosort
);

我想写一些东西,允许更灵活/动态的有效负载排序数据/规则。像这样的东西:

$dynamicSort = "$sort1,SORT_ASC,$sort2,SORT_ASC,$sort3,SORT_ASC,";

array_multisort(
    $dynamicSort, 
    $arraytosort
);

如何向

array_multisort()
提供未知数量的参数并让它修改
$arraytosort
数组?

php sorting dynamic-programming variadic-functions array-multisort
6个回答
5
投票

您可以尝试使用call_user_func_array。但我以前从未在内置函数上尝试过它。这是一个例子:

$dynamicSort = "$sort1,SORT_ASC,$sort2,SORT_ASC,$sort3,SORT_ASC";
$param = array_merge(explode(",", $dynamicSort), array($arrayToSort))
call_user_func_array('array_multisort', $param)

3
投票

我对这个答案有同样的问题:“参数#1应该是一个数组或排序标志”

对于有同样问题的人,请尝试以下方法:

$dynamicSort = array(&$sort1, SORT_ASC, &$sort2, SORT_ASC, &$sort3, SORT_ASC); 
$param = array_merge($dynamicSort, array(&$arrayToSort));
call_user_func_array('array_multisort', $param);

请注意,我使用了对变量“&$”的引用,而不是 $。 这在 php 5.3 中效果很好,但由于 bug 可能会在 5.2 中导致错误。


2
投票

重要的是要理解发送到 call_user_func_array() 的数组必须仅包含引用;数组本身是否通过引用传递并不重要。我花了一天的大部分时间来解决这个问题;事实上 php.net 函数页面上的示例都使用了文字数组,这让我看到了这个页面:php Bug #49353。问题解决了。 这似乎没有很好(或一致)记录,所以这里......

这些不起作用(PHP 5.3.3):

$multisort_array = array($arr1, SORT_DESC, SORT_STRING, $arr2); // array of values call_user_func_array('array_multisort', $multisort_array); // array passed by value $multisort_array = array($arr1, SORT_DESC, SORT_STRING, $arr2); // array of values call_user_func_array('array_multisort', &$multisort_array); // array passed by reference $multisort_array = array(&$arr1, SORT_DESC, SORT_STRING, &$arr2); // non-constants by reference call_user_func_array('array_multisort', $multisort_array); // array passed by value $multisort_array = array(&$arr1, SORT_DESC, SORT_STRING, &$arr2); // non-constants by reference call_user_func_array('array_multisort', &$multisort_array); // array passed by reference

这些确实有效:

$sort = array('desc' => SORT_DESC, 'string' => SORT_STRING); $multisort_array = array(&$arr1, &$sort['desc'], &$sort['string'], &$arr2); // all by reference call_user_func_array('array_multisort', $multisort_array); // array passed by value $sort = array('desc' => SORT_DESC, 'string' => SORT_STRING); $multisort_array = array(&$arr1, &$sort['desc'], &$sort['string'], &$arr2); // all by reference call_user_func_array('array_multisort', &$multisort_array); // array passed by reference



1
投票

//$_POST["sort_by"] = "column_A DESC, column_B ASC, columns_C DESC"; $sort_bys = explode(",", $_POST["sort_by"]); $dynamicSort = array(); foreach($sort_bys as $sort_by){ $sort_by2 = trim(str_replace('DESC','',$sort_by)); $direction = (strpos($sort_by, 'DESC') !== false)?SORT_DESC:SORT_ASC; $$sort_by2 = array_column($array_to_sort, $sort_by2); $dynamicSort[] = &$$sort_by2; $dynamicSort[] = $direction; $dynamicSort[] = SORT_NUMERIC; //or SORT_STRING or SORT_REGULAR ... } $param = array_merge($dynamicSort, array(&$array_to_sort)); call_user_func_array('array_multisort', $param);



1
投票
array_multisort()

中。确保您希望修改的数组可以通过引用进行修改,然后再将其推入参数数组。


将参数推送到下面的

$sortingParams

可以更简洁地编写为单个声明,但我认为这种方式会更容易概念化。这些单独的推送适合迭代过程(例如

foreach()
)。

对于用于对父数组进行排序的每一列数据,您可以选择推送零个、一个或两个附加元素,以最好地表示排序逻辑。

代码:(

演示

$array = [ ['number' => 2, 'letter' => 'a', 'price' => 9.99], ['number' => 3, 'letter' => 'b', 'price' => 9.99], ['number' => 1, 'letter' => 'c', 'price' => 9.50], ['number' => 1, 'letter' => 'd', 'price' => 10], ['number' => 1, 'letter' => 'e', 'price' => 9.99], ]; $sortingParams[] = array_column($array, 'number'); // 1-dimensional $sortingParams[] = SORT_ASC; // this is omittable as well because it is assumed (just for demo) $sortingParams[] = array_column($array, 'price'); // 1-dimensional $sortingParams[] = SORT_DESC; $sortingParams[] = SORT_NUMERIC; // this is omittable as well because it is assumed (just for demo) $sortingParams[] = &$array; // this is the actual master array which should be modified array_multisort(...$sortingParams); // unpack with splat operator var_export($array);

输出:

array ( 0 => array ( 'number' => 1, 'letter' => 'd', 'price' => 10, ), 1 => array ( 'number' => 1, 'letter' => 'e', 'price' => 9.99, ), 2 => array ( 'number' => 1, 'letter' => 'c', 'price' => 9.5, ), 3 => array ( 'number' => 2, 'letter' => 'a', 'price' => 9.99, ), 4 => array ( 'number' => 3, 'letter' => 'b', 'price' => 9.99, ), )

如果您将动态规则传递给您的流程,则此技术非常强大。就我而言,我需要从 DataTables UI 收集过滤器并将数据重新生成为 .csv。我只需要迭代 DataTable 的订单数据并导出我的规则集 - 完成。

我发现这种语法比

call_user_func_array()

对眼睛更友好。


这是一个更复杂的实现:

使用指定的排序规则对多列上的关联数组进行排序


0
投票
$sortColumns

$sortDirections
$sortColumnsArrayColumn = array_map(
    function ($n) use ($mainArray) {
        return array_column($mainArray, $n);
    }, $sortColumns
); //creates "$sort" arrays
                
$columnsAndDirections = array_map(null, $sortColumnsArrayColumn, $sortDirections); // zip both arrays together
$params = array_merge(...$columnsAndDirections); // flatten zipped array
$params[] = &$mainArray; // add reference to the mainArray
array_multisort(...$params);

我仍然收到警告消息,但不知道如何更改:“警告:array_multisort():参数 #2 预计是一个数组或排序标志”

© www.soinside.com 2019 - 2024. All rights reserved.