在PHP中动态分组多个字段的数据

时间:2012-10-26 11:01:15

标签: php multidimensional-array grouping

我想按字段对关联数组进行分组。该数组本身最初来自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");
    }
}
?>

但是我怎么能用任意数量的字段动态地做呢?

2 个答案:

答案 0 :(得分:2)

我不确定这段代码是如何为你起作用的,但是有些东西是错的,可能不允许代码正常运行

  • 字段只有一个值,

    $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
                )

        )

)

答案 1 :(得分:1)

而不是在你的$data foreach循环中使用if / elseif / else(它总是限于你用那个结构编写的数字和大量的代码复制),你需要转向if / elseif / else进入它自己的循环。

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

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

$val应分配给由$parsedData名称$fields ue键控的数组$val。我们在这里压缩它,名称中的数字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
}