将平面数组转换为按类别

时间:2017-09-29 13:51:09

标签: php arrays

我有一个如下所示的数据库表:

uid | group  | category
1   | group1 | cat1
2   | group1 | cat2
3   | group2 | cat3
4   | group2 | cat4
5   | group2 | cat5
6   | group3 | cat6
7   | group3 | cat7

但是我需要在数组中使用这些数据,这些数据按照group对类别进行分组。

例如,我的数组应如下所示:

Array
(
    [group1] => Array
        (
            [0] => Array
                (
                    [0] => 1
                    [1] => cat1

                )

            [1] => Array
                (
                    [0] => 2
                    [1] => cat2
                )

        )

    [group2] => Array
        (
            [0] => Array
                (
                    [0] => 3
                    [1] => cat3
                )

            [1] => Array
                (
                    [0] => 4
                    [1] => cat4
                )

            [2] => Array
                (
                    [0] => 5
                    [1] => cat5
                )

        )

    [group3] => Array
        (
            [0] => Array
                (
                    [0] => 6
                    [1] => cat6
                )
            [1] => Array
                (
                    [0] => 7
                    [1] => cat7
                )

        )

)

我已经编写了一个foreach循环,但是我有一个问题。

我的问题是它总是遗漏表格的最后一行,我不知道如何解决它。在我看来,逻辑规定它应该始终有效。

我想在循环之后我可以将最后一行添加到新数组中,但我认为如果最后一行有不同的组可能会导致问题,我宁愿将解决方案构建到foreach中循环。

不幸的是,我在这里不知所措。如何修复我的代码以包含数据库查询的最后一行?

我也有兴趣看看我可以对当前代码做出哪些改进,但对于代码审查来说这可能是一个更好的问题。

我的循环:

$pass = [];
foreach($stmt as $key => $value) {
    if(empty($currentGroup)) $currentGroup = $value['group'];
    if(empty($temp)) $temp = [];
    if($currentGroup != $value['group'] || $key+1 == count($stmt)) {
        $pass[$currentGroup] = $temp;
        $currentGroup = $value['group'];
        $temp = [];
        $temp[] = [$stmt[$key]['uid'], $stmt[$key]['category']];
    } else {
        $temp[] = [$stmt[$key]['uid'], $stmt[$key]['category']];
    }
}

2 个答案:

答案 0 :(得分:3)

以下应该这样做:

<?php

//Create an array to store our grouped rows
$grouped = array();

//Loop over all rows returned by the $stmt that has been executed.
//You could probably remove the key from here, it's not needed it seems.
//The keys within the $value array will match the names of the columns in 
//the database,
foreach($stmt as $key => $value){

    //As we're storing by the group value from the row we first want to
    //check if our grouped array contains a key for the group of the row
    //being processed. If it does not, create an empty array within the
    //grouped data for this group.
    if(!array_key_exists($value['group'], $grouped)){
        $grouped[$value['group']] = array();
    }

    //Knowing we will always have an array element for the rows group
    //we can blindly append the values for this row to the grouped 
    //container using its values.
    //'[] =' is just short hand append.
    $grouped[$value['group']][] = array(
        $value['uid'],
        $value['category']
    );
}

希望有所帮助!

为了进一步证明此循环,您可以将分组值附加更改为以下内容:

<?php

//Setting the whole row (minus the group) rather than just the uid 
//and category explicitly allows this code to work without modification
//as the datatable changes, ie. new columns. Assuming that is the 'group'
//column remains present
unset($value['group']);
$grouped[$value['group']][] = $value;

现在可以使用以下方法访问分组内容数据:

<?php

//Acceess data via column name not array index, yay!
echo $grouped['group1']['uid']

答案 1 :(得分:0)

我最近又需要这个,所以我根据@JParkinson1991的答案做了一个函数。

我把它放在这里用于记录,并可能帮助未来的读者。

function groupArray($arr, $group, $preserveSubArrays = false, $preserveGroupKey = false) {
    $temp = array();
    foreach($arr as $key => $value) {
        $groupValue = $value[$group];
        if(!$preserveGroupKey)
        {
            unset($arr[$key][$group]);
        }
        if(!array_key_exists($groupValue, $temp)) {
            $temp[$groupValue] = array();
        }

        if(!$preserveSubArrays){
            $data = count($arr[$key]) == 1? array_pop($arr[$key]) : $arr[$key];
        } else {
            $data = $arr[$key];
        }
        $temp[$groupValue][] = $data;
    }
    return $temp;
}

击穿

function groupArray($arr, $group, $preserveGroupKey = false, $preserveSubArrays = false)

此功能接受2到4个参数。

  1. 要分组的平面阵列(数组)
  2. 要分组的键(string / int)
  3. 在每个子数组的输出中保留组键的选项(布尔值)
  4. 保留子数组的选项。如果每个子数组中只存在1个键,则该函数将仅存储每行的单个值而不是数组(布尔值)
  5. 第一个参数是数组本身,第二个参数是您要分组的键,第三个(可选)参数是一个布尔值,它告诉函数是否要保留子数组中的组键

    $temp = array();
    foreach($arr as $key => $value) {
        $groupValue = $value[$group];
        if(!$preserveGroupKey)
        {
            unset($arr[$key][$group]);
        }
        if(!array_key_exists($groupValue, $temp)) {
            $temp[$groupValue] = array();
        }
        $temp[$groupValue][] = $arr[$key];
    }
    

    首先,我们创建一个名为$temp

    的临时数组

    接下来,我们遍历数组抓取键(应该是一个字符串或int),以及值(应该是一个数组)。

    我们将$groupValue设置为您选择的$group的值,例如下面示例中的“group”。

    $arr = [
        0 => [
            "group" => "group1",
            "name" => "Bob",
        ],
        1 => [
            "group" => "group1",
            "name" => "Randy",
        ],
        2 => [
            "group" => "group1",
            "name" => "Susan",
        ],
        3 => [
            "group" => "group2",
            "name" => "Larry",
        ],
        4 => [
            "group" => "group2",
            "name" => "David",
        ],
        5 => [
            "group" => "group3",
            "name" => "Perry",
        ],
    ];
    

    然后我们检查是否要$preserveGroupKey。如果此布尔值为false(并且默认情况下是这样),则将删除该键,留下几个仅包含“name”键的子数组。

    现在我们检查$groupValue数组中是否存在$temp,如果不存在,我们会创建它。

    然后我们将$temp[$groupValue]添加到当前行值。从上面的例子中,我们最终得到:

    Array
    (
        [group1] => Array
            (
                [0] => Bob
                [1] => Randy
                [2] => Susan
            )
    
        [group2] => Array
            (
                [0] => Larry
                [1] => David
            )
    
        [group3] => Array
            (
                [0] => Perry
            )
    
    )
    

    或者,将第3个参数设置为true,您将得到:

    Array
    (
        [group1] => Array
            (
                [0] => Array
                    (
                        [name] => Bob
                    )
    
                [1] => Array
                    (
                        [name] => Randy
                    )
    
                [2] => Array
                    (
                        [name] => Susan
                    )
    
            )
    
        [group2] => Array
            (
                [0] => Array
                    (
                        [name] => Larry
                    )
    
                [1] => Array
                    (
                        [name] => David
                    )
    
            )
    
        [group3] => Array
            (
                [0] => Array
                    (
                        [name] => Perry
                    )
    
            )
    
    )