0

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

但是我怎样才能用任意数量的字段动态地做到这一点呢?

4

2 回答 2

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
                )

        )

)
于 2012-10-26T14:49:49.510 回答
1

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

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

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

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

$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
}
于 2012-10-26T11:33:17.340 回答