PHP - 当给定子键名称时,递归地将每个数组元素的键设置为子元素的值

标签 php arrays recursion multidimensional-array pass-by-reference

我将首先展示一个非递归示例

非递归示例

$given_key_name = 'site_id';

$rows[] = array(
    'site_id' => '0',
    'language_id' => '1',
    'name' => 'sitename',
    'description' =>'site desc',
);

$results = array();
foreach($rows as $row){
    $key_value = $row[$given_key_name];
    unset($row[$given_key_name]);
    $results[$key_value] = $row;
}

//  OR This method is faster than the forloop

$results = array_combine(array_column($rows, $given_key_name),$rows);
foreach($results as &$row){
    unset($row[$given_key_name]); 
}

$results 等于

$results[0] = array( 
    'language_id' => '1',
    'name' => 'sitename',
    'description' =>'site desc',
);

很简单,键名已设置为给定子元素的值。但我希望能够通过使用多个键名称来嵌套和取消嵌套。

示例

$given_key_names = array('site_id', 'language_id');

在这种情况下,所需的结果是。

$结果[0][1] = 数组( '名称' => '网站名称', '描述'=>'站点描述', );

说明

第一个键值已用作 $results 数组中的第一个键,并创建一个新的空数组作为其值。 $results[0] = array();

由于存在第二个键,因此它的值被设置为新创建的数组的键,并且它的值也是一个新的空数组。 $results[0][1] = array();

由于没有更多的键,空数组将填充剩余的值

$结果[0][1] = 数组( '名称' => '网站名称', '描述'=>'站点描述', );

所以我想要两个函数nestByKeyNamesunNestByKeyName

NestByKeyNames 函数

Christians Answer solves this

function nestByKeyNames($arrayRows, $arrayKeyOrder){

    // Prepare resulting array
    $arrayResult = array();

    // Cycle the input array
    foreach($arrayRows as $someRow){
        // We will acomplish this using references
        $current = &$arrayResult;

        // get the current level
        foreach($arrayKeyOrder as $someKey){
            $someValue = $someRow[$someKey];
            if(isset($current[$someValue])){
                $current = &$current[$someValue];
            }else{
                $current[$someValue] = array();
                $current = &$current[$someValue];
            }
            unset($someRow[$someKey]);
        }
        $current = $someRow;
    }
    return $arrayResult;
}

我想知道是否可以使用array_combine(array_column($arrayRows, $key_name),$arrayRows);代替第一次迭代来提高性能?

这表示 mysql select 语句的结果。

$rows = array(
    array(
        'pri_id_1' =>1,
        'pri_id_2' =>1,
        'pri_id_3' =>1,
        'col_1' =>'col_value_1111',
        'col_2' =>'col_value_1112',
        'col_3' =>'col_value_1113',
    ),
    array(
        'pri_id_1' =>1,
        'pri_id_2' =>2,
        'pri_id_3' =>1,
        'col_1' =>'col_value_1211',
        'col_2' =>'col_value_1212',
        'col_3' =>'col_value_1213',
    ),
    array(
        'pri_id_1' =>1,
        'pri_id_2' =>3,
        'pri_id_3' =>1,
        'col_1' =>'col_value_1311',
        'col_2' =>'col_value_1312',
        'col_3' =>'col_value_1313',
    )
);

$keyNames = array('pri_id_1','pri_id_2','pri_id_3');
$results = nestByKeyNames($rows, $keyNames);

产生以下输出

Array
(
    [1] => Array
        (
            [1] => Array
                (
                    [1] => Array
                        (
                            [col_1] => col_value_1111
                            [col_2] => col_value_1112
                            [col_3] => col_value_1113
                        )

                )

            [2] => Array
                (
                    [1] => Array
                        (
                            [col_1] => col_value_1211
                            [col_2] => col_value_1212
                            [col_3] => col_value_1213
                        )

                )

            [3] => Array
                (
                    [1] => Array
                        (
                            [col_1] => col_value_1311
                            [col_2] => col_value_1312
                            [col_3] => col_value_1313
                        )

                )

        )

)

UnNestByKeyNames 函数

unNestByKeyNames 应该能够获取此输出并将其转换回原始数组(前提是给定了键名称)。 Christians Answer没有解决这个问题,因为它不能使用单个键名,但我可以说它非常接近。

function unNestByKeyNames($arrayRows, $arrayKeyOrder){


}

$keyNames = array('pri_id_1','pri_id_2','pri_id_3');
$rows = unNestKeyNames($results, $keyNames);

我的真正目标是从 MYSQL SELECT 语句获取结果,并使用 nestByKeyNames 使用相同的命名约定填充表单。

例如

<input name="rows[1][1][1][col_1]" value="col_value_1" />

然后首先使用 unNestByKeyNames 将 $_POST 请求转换回 MYSQL INSERT 语句。

由此我将创建一个 INSERT 语句。

function returnValues($rows, $column_names){

    //validation has been removed for clarity

    $implode_VALUES = array();

    foreach ($rows as $key => $row) {
        $implode_row_values = array();
        foreach ($column_names as $column_name) {
            $implode_row_values[$column_name] = $row[$column_name];
        }
        if($implode_row_values){
            $implode_VALUES[] = " ('" . implode("','", $implode_row_values) . "') ";
        }
    }
    return $implode_VALUES;
}

$implode_COLUMNS = array('pri_id_1','pri_id_2','pri_id_3','col_1','col_2','col_3');

$implode_VALUES = returnValues($rows, $implode_COLUMNS)

$sql = "INSERT INTO table_name (" . implode(',', $implode_COLUMNS) . ") VALUES " . implode(',', $implode_VALUES);

最终结果应该产生这样的sql语句

INSERT INTO table_name (pri_id_1,pri_id_2,pri_id_3,col_1,col_2,col_3) VALUES ('1','1','1','NEW_value_1111','NEW_value_1112','NEW_value_1113') , ( '1','2','1','NEW_value_1211','NEW_value_1212','NEW_value_1213') , ('1','3','1','NEW_value_1311','NEW_value_1312','NEW_value_1313')

我想要什么

  • 对“nestByKeyNames”功能的改进建议(性能/是否有错误)
  • 帮助生成“unNestByKeyNames”代码
  • 对我的“$rows to mysql INSERT”方法的改进建议
  • 有关如何使我的任何代码性能更好的示例。

最佳答案

这比我最初想象的要棘手,但我相信我有一个困惑的解决方案。

首先,这是我正在使用的数据。 dumpr 是一个自定义函数,可以更好地格式化 var_dump

$arrayKeyOrder = array(
    'site_id',
    'language_id'
);

$original = array(
    array(
        'site_id' => '0',
        'language_id' => '1',
        'name' => 'sitename',
        'description' =>'site desc',
    ),

    array(
        'site_id' => '0',
        'language_id' => '2',
        'name' => 'sitename',
        'description' =>'site desc',
    ),

    array(
        'site_id' => '1',
        'language_id' => '1',
        'name' => 'sitename',
        'description' =>'site desc',
    ),

    array(
        'site_id' => '2',
        'language_id' => '1',
        'name' => 'sitename',
        'description' =>'site desc',
    ),
);

$zipped = doZip($original, $arrayKeyOrder);
$unzipped = unZip($zipped, $arrayKeyOrder);

dumpr($original);
dumpr($zipped);
dumpr($unzipped);

这是压缩和解压缩函数:

function doZip($arrayRows, $arrayKeyOrder){

    // Prepare resulting array
    $arrayResult = array();

    // Cycle the input array
    foreach($arrayRows as $someRow){
        // We will acomplish this using references
        $current = &$arrayResult;

        // get the current level
        foreach($arrayKeyOrder as $someKey){
            $someValue = $someRow[$someKey];
            if(isset($current[$someValue])){
                $current = &$current[$someValue];
            }else{
                $current[$someValue] = array();
                $current = &$current[$someValue];
            }
            unset($someRow[$someKey]);
        }

        $current = $someRow;
    }

    return $arrayResult;
}


function unZip($arrayRows, $arrayKeyOrder, $arrayValues = array(), $depth = 0){

    $arrayResults = array();

    if($depth < count($arrayKeyOrder)){
        foreach($arrayRows as $key => $value){
            $arrayValues[$depth] = $key;
            $arrayResults[] =  unZip($value, $arrayKeyOrder, $arrayValues, $depth + 1);
        }
    }else{
        $extra = array_combine($arrayKeyOrder, $arrayValues);
        $result = array_merge($extra, $arrayRows);
        return $result;
    }

    if($depth == 0){
        for($i = 1; $i < count($arrayKeyOrder); $i++){
            $arrayResults = call_user_func_array('array_merge', $arrayResults);
        }        
    }

    return $arrayResults;
}

最后,这是输出。让我知道这是否是您所要求的以及它在更大的数据集上是否正常工作。

/vhost/virtual/sandbox/public/index.php:54
array(4) {
    [0] = array(4) {
        [site_id] = string(1) "0"
        [language_id] = string(1) "1"
        [name] = string(8) "sitename"
        [description] = string(9) "site desc"
    }
    [1] = array(4) {
        [site_id] = string(1) "0"
        [language_id] = string(1) "2"
        [name] = string(8) "sitename"
        [description] = string(9) "site desc"
    }
    [2] = array(4) {
        [site_id] = string(1) "1"
        [language_id] = string(1) "1"
        [name] = string(8) "sitename"
        [description] = string(9) "site desc"
    }
    [3] = array(4) {
        [site_id] = string(1) "2"
        [language_id] = string(1) "1"
        [name] = string(8) "sitename"
        [description] = string(9) "site desc"
    }
}

/vhost/virtual/sandbox/public/index.php:55
array(3) {
    [0] = array(2) {
        [1] = array(2) {
            [name] = string(8) "sitename"
            [description] = string(9) "site desc"
        }
        [2] = array(2) {
            [name] = string(8) "sitename"
            [description] = string(9) "site desc"
        }
    }
    [1] = array(1) {
        [1] = array(2) {
            [name] = string(8) "sitename"
            [description] = string(9) "site desc"
        }
    }
    [2] = array(1) {
        [1] = array(2) {
            [name] = string(8) "sitename"
            [description] = string(9) "site desc"
        }
    }
}

/vhost/virtual/sandbox/public/index.php:56
array(4) {
    [0] = array(4) {
        [site_id] = int(1) 0
        [language_id] = int(1) 1
        [name] = string(8) "sitename"
        [description] = string(9) "site desc"
    }
    [1] = array(4) {
        [site_id] = int(1) 0
        [language_id] = int(1) 2
        [name] = string(8) "sitename"
        [description] = string(9) "site desc"
    }
    [2] = array(4) {
        [site_id] = int(1) 1
        [language_id] = int(1) 1
        [name] = string(8) "sitename"
        [description] = string(9) "site desc"
    }
    [3] = array(4) {
        [site_id] = int(1) 2
        [language_id] = int(1) 1
        [name] = string(8) "sitename"
        [description] = string(9) "site desc"
    }
}

关于PHP - 当给定子键名称时,递归地将每个数组元素的键设置为子元素的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33877081/

相关文章:

python - 这个递归二进制代码函数是如何工作的?

c++ - 按升序遍历树

java - 嵌套递归错误

php - Composer 安装失败,出现总线错误 : 10

php - 如何使用 Mysql 数据填充下拉列表的选定值?

c++ - 无法删除数组(我不知道的错误)

c - 使用 C 的 getline() 时出现奇怪的行为

mysql - 使用 PDO 的 undefined variable

php - WordPress:ACF 将行添加到转发器字段

python - 对 numpy 数组中的每一行应用函数?