array_multisort和动态变量选项

时间:2010-03-19 02:55:45

标签: php

我试图用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
);

有什么建议吗?

5 个答案:

答案 0 :(得分:4)

您可以尝试使用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)

答案 1 :(得分: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中效果很好,但由于错误可能会导致5.2中的错误。

答案 2 :(得分:1)

重要的是要理解发送到call_user_func_array()的数组必须包含的引用;数组本身是否通过引用传递并不重要。我花了一天的时间来解决这个问题。事实上,php.net的函数页面上的示例都使用了文字数组,这使我进入了这个页面:php Bug #49353。问题解决了。

这似乎没有很好(或一贯)记录,所以这里...... [/ p>

这些不起作用(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

这些DO WORK:

$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

答案 3 :(得分:1)

要添加到现有答案中,只是以为我会添加一些内容。对于将所需的“排序依据”作为逗号分隔的$ _POST变量(或与此相关的任何逗号分隔的变量)进行传递的人:

//$_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);

答案 4 :(得分:0)

从PHP5.6开始,您可以使用可变参数技术。只需将所有排序数据和排序逻辑推入索引数组,然后使用splat运算符将参数解压缩到array_multisort()中即可。在将其放入参数数组之前,请确保要修改的数组可以通过引用进行修改。

将参数推入下面的$sortingParams可以更简洁地作为一个声明来编写,但是我认为这样更容易概念化。这些单独的推送将适合在迭代过程(例如foreach())内部进行。

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

代码:(Demo

$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()相比,我觉得这种语法更实用。

这是一个更复杂的实现:Sort array of associative arrays on multiple columns using specified sorting rules