如何透过这个数组

时间:2016-04-17 04:18:41

标签: php

我想转换一下:

$arr = [
        [
            'type' => 'fruit',
            'name' => 'apple',
            'cost' => 1
        ],
        [
            'type' => 'fruit',
            'name' => 'orange',
            'cost' => 2
        ],
        [
            'type' => 'vegetable',
            'name' => 'carrot',
            'cost' => 2.5
        ],
        [
            'type' => 'vegetable',
            'name' => 'avocado',
            'cost' => 3.5
        ]
    ];

进入这个:

$arr = [
        [
            'type' => 'fruit',
            'apple' => '1',
            'orange' => 2
        ],
        [
            'type' => 'vegetable',
            'carrot' => 2.5,
            'avocado' => 3.5
        ]
    ];

正如您所看到的,我将每种类型分组到一个数组中并转动水果名称和成本。

有什么想法吗?

感谢。

3 个答案:

答案 0 :(得分:1)

对于像这样的东西,简单地循环遍历你的数组,正如Rizier建议应该做的那样。如果按类型进行分组,最好将类型用作数组键,因此格式与您要求的格式略有不同。您可以像这样访问生成的数组:

$fruitItems = $newArr['fruit'];

以下是示例代码:

$size = count($itemArray);
$newArr = []; //The array you want to create
for ($i = 0; $i < $size; $i++)
{
    $item = $itemArray[$i];
    $type = $item['type'];
    $name = $item['name'];
    $cost = $item['cost']
    //If your new array doesn't have this type yet, make a sub-array
    //with the type as key
    if (!isset($newArr[$type]))
        $newArr[$type] = [];
    $newArr[$type][$name] = $cost; //In your type sub-array, add the new item
}

如果你必须创建一个具有该结构的数组,你可以稍微调整上面的代码来搜索你的数组并找到具有正确类型的子数组。然而,这看起来有点复杂。

答案 1 :(得分:1)

这是一种在输出中获得精确数组结构的方法。这比我想象的要复杂得多:

//first build groups by type
$groups = array();

foreach($arr as $key => $array){
    //$type is not necessary, it's just for clarity below
    $type = $array['type'];

    if( !isset($groups[$type]) ){
        $groups[$type] = array();
        $groups[$type]['type'] = $array['type'];
    }
    $groups[$type][$array['name']] = $array['cost'];

}
//then combine the groups into a master array
$out = array();
foreach($groups as $g){
    $out[] = $g;
}
echo '<pre>'. print_r($out, true).'</pre>';

答案 2 :(得分:0)

万一某个人需要更多通用方法,并且不得不处理同一列中的多个值,我会稍微扩大@larsAnders解决方案。

用法(获取确切的所需输出):

$pivot_fruits = arr_pivot($arr, 'type', 'name', 'cost', 'sum', false, false); 

功能:

function arr_pivot(
    $arr,
    $arr_key_to_pivot_for_rows,
    $arr_key_to_pivot_for_columns,
    $arr_key_to_pivot_for_values,
    $grouping_method = "sum",
    $add_missing_columns=true,
    $sort_columns=true){

    if(!is_array($arr)) return false;

    $pivot_row = $arr_key_to_pivot_for_rows;
    $pivot_col = $arr_key_to_pivot_for_columns;
    $pivot_val = $arr_key_to_pivot_for_values;

    //first build groups by $col_name_to_pivot_for_rows
    $row_groups = [];
    $columns=[];
    foreach ($arr as $row_key => $row) {
        $group_label = $row[$pivot_row];
        $col_label = $row[$pivot_col];
        $value = $row[$pivot_val];
        if( !isset($row_groups[$group_label]) ){
            $row_groups[$group_label]=[];
            $row_groups[$group_label][$pivot_row] = $group_label;
        }
        if(!isset($columns[$col_label])) $columns[$col_label]=[];
        $row_groups[$group_label][$col_label][]=$value;
    }

    //then combine the groups into a return array
    $arr_pivoted = [];
    foreach($row_groups as $row_group){

        //all columns except of the first one are pivoted columns. split into the row name and the columns itself
        $row_group_columns = $row_group;
        $row_group_row = array_shift($row_group_columns);

        //ensure that all groups have all columns
        if($add_missing_columns) $row_group_columns = array_merge($columns,$row_group_columns);
        if($sort_columns) ksort($row_group_columns);

        $row_group_columns_grouped=[];

        //apply grouping function to columns
        foreach ($row_group_columns as $column_name => $row_group_column){
            $acount=count($row_group_column);
            switch ($grouping_method){
                default:
                case 'sum':
                    $row_group_columns_grouped[$column_name] = array_sum($row_group_column);
                    break;
                case 'avg':
                    $row_group_columns_grouped[$column_name] = $acount == 0 ? 0 : array_sum($row_group_column) / count($row_group_column);
                    break;
                case 'count':
                    $row_group_columns_grouped[$column_name] = count($row_group_column);
                    break;
                case 'max':
                    $row_group_columns_grouped[$column_name] = $acount == 0 ? 0 : max($row_group_column);
                    break;
                case 'min':
                    $row_group_columns_grouped[$column_name] = $acount == 0 ? 0 : min($row_group_column);
                    break;
                case 'concat':
                case 'implode':
                    $row_group_columns_grouped[$column_name] = implode(',',$row_group_column);
                    break;
            }
        }
        $arr_pivoted[] = array_merge([$pivot_row=>$row_group_row],$row_group_columns_grouped);
    }
    return $arr_pivoted;
}

PHPDoc:

/**
 * Turns 2 dimensional array in a pivoted version
 *
 * @param array     $arr                            2 dimensional to pivot
 * @param string    $arr_key_to_pivot_for_rows      input array key to use as rows
 * @param string    $arr_key_to_pivot_for_columns   input array key to use as columns
 * @param string    $arr_key_to_pivot_for_values    input array key to use as values
 * @param string    $grouping_method                method to use on values out of sum|count|avg|min|max|concat. If values are not numeric use count or concat
 * @param bool      $add_missing_columns            if true all occurring columns in any row are added if missing
 * @param bool      $sort_columns                   if true all columns will be sorted by column name (=key)
 * @return array|bool                               false if input is not an array otherwise the pivoted result as 2 dimensional array
 */

如果有人有改进编码风格,输入验证和/或变量命名的冲动,我将非常高兴。