【问题标题】:Group data by multiple fields dynamically in PHP在 PHP 中按多个字段动态分组数据
【发布时间】:2012-10-26 11:01:15
【问题描述】:

我想按字段对关联数组进行分组。数组本身最初来自 mysql 数据库查询。

下面是我如何通过硬编码实现它的示例:

<?php
$fields = array("ID,subID");
$fieldCounts = count($fields);
$data = array(); //there is sql querieed data



$parsedData = array();

foreach ($data as $val)
{
    if ($fieldCounts == 1)
    {
        $f0 = $fields[0];
        $fv0 = $val[$f0];
        $parsedData[$fv0][] = $val;
    }
    else if ($fieldCounts == 2)
    {
        $f0 = $fields[0];
        $fv0 = $val[$f0];
        $f1 = $fields[10];
        $fv1 = $val[$f1];
        $parsedData[$fv0][$f1][] = $val;
    }
    else
    {
        exit("Third field not implemented");
    }
}
?>

但是我怎样才能动态地使用任意数量的字段呢?

【问题讨论】:

标签: php multidimensional-array grouping


【解决方案1】:

我不确定这段代码对你有什么作用,但有些事情是错误的,可能无法让代码正常运行

  • Fields 的值只有一个 ,

    $fields = array("ID,subID"); 
                       ^----------- between string 
    

    代替

    $fields = array("ID","subID");
    
  • 注意:未定义的偏移量:

    $f1 = $fields[10];
                   ^----- your array is not up to 10
    

由于您没有放置生成数据和所需的输出。我会假设你的最终输出并生成一些临时数据

$fields = array("ID","subID"); //You can Increase or decrease this Fields
$fieldCounts = count($fields);
$data = array(); // there is sql querieed data

for($i = 0; $i < 3; $i ++) {
    $data[] = array("ID" => mt_rand(1, 1000),"subID" => "sub" . mt_rand(100, 900));
}

上面的 2 个更正会破坏你的代码

foreach ( $data as $val ) {
    if ($fieldCounts == 1) {
        $f0 = $fields[0];
        $fv0 = $val[$f0];
        $parsedData[$fv0][] = $val;
    } else if ($fieldCounts == 2) {
        $f0 = $fields[0];
        $fv0 = $val[$f0];
        $f1 = $fields[1];
        $fv1 = $val[$f1];
        $parsedData[$fv0][$f1][] = $val;
    } else {
        exit("Third field not implemented");
    }
}

输出

Array
(
    [159] => Array
        (
            [subID] => Array  <----------- SubID is fixed in your can cause confict
                (
                    [0] => Array
                        (
                            [ID] => 159
                            [subID] => sub589
                        )

                )

        )

    [334] => Array
        (
            [subID] => Array
                (
                    [0] => Array
                        (
                            [ID] => 334
                            [subID] => sub703
                        )

                )

        )

)

比你更好的替代品

$parsedData = array();
foreach ( $data as $val ) {
    $temp = &$parsedData;
    foreach ( array_slice($val, 0, $fieldCounts) as $key ) {
        $temp = &$temp[$key];
    }
    $temp[] = $val;
}
print_r($parsedData);

输出

Array
(
    [159] => Array
        (
            [sub589] => Array <---------- Make Sub ID Dynamic 
                (
                    [0] => Array
                        (
                            [ID] => 159
                            [subID] => sub589
                        )

                )

        )

    [334] => Array
        (
            [sub703] => Array
                (
                    [0] => Array
                        (
                            [ID] => 334
                            [subID] => sub703
                        )

                )

        )

)

推荐版本便于数组路径

$parsedData = array();
foreach ( $data as $val ) {
    $temp = &$parsedData;
    foreach ( array_slice($val, 0, $fieldCounts) as $key ) {
        $temp = &$temp[$key];
    }
    $temp = $val; 
}
print_r($parsedData);

输出

Array
(
    [159] => Array
        (
            [sub589] => Array <---- Easy to asses as $parsedData['159']['sub589']
                (
                    [ID] => 159
                    [subID] => sub589
                )

        )

    [334] => Array
        (
            [sub703] => Array
                (
                    [ID] => 334
                    [subID] => sub703
                )

        )

)

【讨论】:

    【解决方案2】:

    而不是在你的$data foreach 循环中执行 if/elseif/else(它总是限制在你用那个结构和很多代码重复的地方“写”的数字)你需要把它转成 if /elseif/else 进入它自己的循环。

    但首先转换现有代码,我从第一个 if 正文开始,它已经包含 所有必要的代码

    $f0  = $fields[0];
    $fv0 = $val[$f0];
    $parsedData[$fv0][] = $val;
    

    $val 应分配给数组$parsedData,该数组由$fields 名称$value 键入。让我们在这里压缩一下,名称中的数字 0 是多余的,因为我们不再需要它(但可能是第一个):

    $field = $fields[0];
    $value = $values[$field];
    
    $parsedData[$value][] = $values;
    

    (我将$val 更改为$values 以改进命名)。这现在更容易阅读和理解。我们也更容易在这里发现神奇的数字0

    现在开始魔术。我们想在这里添加一个数组(推):

    $parsedData[$value][] = $values;
    

    为了使这更容易,让我们把它变成这样:

    $array   = &$parsedData[$value];
    $array[] = $values;
    

    这个现在看起来是多余的,但是当它变成一个循环时,它会变得更加清晰:

    $array   = &$parsedData;
    
    ...
    
    $array   = &array[$value];
    
    ...
    
    $array[] = $values;
    

    现在让我们回顾一下带有外循环的代码:

    foreach ($data as $values)
    {
    
        $array   = &$parsedData; 
    
        $field = $fields[0];
        $value = $values[$field];        
        $array = &$array[$value];
    
        $array[] = $values;
    }
    

    显然这段代码还不完整。内循环不见了,但它开始得到某种身体。实际上内部循环很容易实现:

    $array   = &$parsedData; 
    
    foreach ($fields as $field)
    {
        $value = $values[$field];
        $array = &$array[$value];
    }
    
    $array[] = $values;
    

    就是这样。单个字段已变成对所有字段的迭代。迭代中每个步骤的子数组的别名/引用允许在内循环完成后将值推送到适当的数组条目。

    整个外循环和内循环:

    foreach ($data as $values)
    {
        $array   = &$parsedData; # set reference
    
        foreach ($fields as $field)
        {
            $value = $values[$field];
            $array = &$array[$value];
        }
    
        $array[] = $values;
    
        unset($array); # remove reference
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-28
      • 2013-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多