I'll start by showing a non-recursive example
我将首先展示一个非递归示例
Non- recursive example
非递归的例子
$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
Equals
结果等于美元
$results[0] = array(
'language_id' => '1',
'name' => 'sitename',
'description' =>'site desc',
);
Simple, the key name has been set to the value of the given child element. But I would like to be able to nest and unnest by using multiple key names.
很简单,键名被设置为给定子元素的值。但是我希望能够通过使用多个键名来进行嵌套和反嵌套。
Example
例子
$given_key_names = array('site_id', 'language_id');
$ given_key_names =数组(“site_id”、“language_id”);
In this case the required result would be.
在这种情况下,所需的结果是。
$results[0][1] = array( 'name' => 'sitename', 'description' =>'site desc', );
$results[0][1] = array('name' =>' sitename', 'description' =>'site desc',);
Explanation
解释
The first keys value has been used as the first key in the $results array and a new empty array is created as its value. $results[0] = array();
第一个键值被用作$results数组中的第一个键,并创建一个新的空数组作为其值。数组$结果[0]=();
As there is a second key, its value is set as a key to the newly created array and its value is also a new empty array. $results[0][1] = array()
;
由于有第二个键,它的值被设置为新创建数组的键,它的值也是一个新的空数组。$[0][1]=结果数组();
As there are no more keys the empty array is populated with the remaining values
由于不再有键,空数组将使用剩余的值填充
$results[0][1] = array( 'name' => 'sitename', 'description' =>'site desc', );
$results[0][1] = array('name' =>' sitename', 'description' =>'site desc',);
so i would like two functions nestByKeyNames
and unNestByKeyName
.
所以我想要两个函数nestByKeyNames和unNestByKeyName。
NestByKeyNames Function
基督徒回答解决了这个
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;
}
I wonder whether array_combine(array_column($arrayRows, $key_name),$arrayRows);
could be used instead of the first iteration to improve performance?
我想知道array_combine(array_column) ($arrayRows, $key_name),$arrayRows;可以代替第一次迭代来提高性能吗?
This represents the results from a mysql select statement.
这表示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);
The following output is produced
生成以下输出
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 Function
unNestByKeyNames should be able to take this output and convert it back to the original array providing that it is given the key names. Christians Answer did not solves this as it doesnt work with a single key name but i can tell its very close.
unNestByKeyNames应该能够获取该输出并将其转换回原始数组,前提是它具有键名。基督教徒的回答没有解决这个问题,因为它没有一个键名,但是我可以很清楚地告诉你。
function unNestByKeyNames($arrayRows, $arrayKeyOrder){
}
$keyNames = array('pri_id_1','pri_id_2','pri_id_3');
$rows = unNestKeyNames($results, $keyNames);
My true goal is to take the results from MYSQL SELECT
statement and populate a form using the same naming convention by using nestByKeyNames
.
我真正的目标是获取MYSQL SELECT语句的结果,并使用nestByKeyNames使用相同的命名约定填充表单。
e.g.
如。
<input name="rows[1][1][1][col_1]" value="col_value_1" />
and then convert the $_POST request back into an MYSQL INSERT
statement by first using unNestByKeyNames
.
然后使用unNestByKeyNames将$_POST请求转换回MYSQL INSERT语句。
From this i will create an INSERT
statement.
从这里,我将创建一个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);
The final result should produce a sql statement like so
最终的结果应该生成这样的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')
插入table_name(pri_id_1 pri_id_2、pri_id_3 col_1,col_2,col_3)值(' 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’)
What I Would like
我想
- Improvement suggestions on the 'nestByKeyNames' function (performance/ does it have bugs)
- 关于“nestByKeyNames”函数的改进建议(性能/是否有bug)
- help producing 'unNestByKeyNames' code
- 帮助生产“unNestByKeyNames”代码
- Improvement suggestions on my '$rows to mysql INSERT' approach
- 关于我的“$row to mysql INSERT”方法的改进建议
- examples of how i could make any of my code perform better.
- 如何使我的代码执行得更好的例子。
5 个解决方案
#1
5
This was trickier than I first imagined but I believe I have a messy solution.
这比我最初想象的要棘手,但我相信我有一个混乱的解决方案。
First of all, this is the data I am working with. dumpr
is a custom function that formats var_dump
better.
首先,这是我正在处理的数据。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);
Here is the zip and unzip functions:
这里是zip和unzip功能:
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;
}
And finally, here is the output. let me know if this is what you were asking for and if it worked OK on a larger data-set.
最后,这是输出。请让我知道这是否是您所要求的,以及它在更大的数据集上是否工作正常。
/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"
}
}
#2
0
Try this:
试试这个:
// initialize your array
$all_rows = array();
// loop through query results
while( $row = $qry->fetch_assoc() )
{
// temporarily store these vars for easy use later
$s_id = $row['site_id'];
$l_id = $row['language_id'];
// create an empty array based on site_id and language_id
$all_rows[ $s_id ][ $l_id ] = array();
// loop through all columns returned from query
foreach ( $row as $key => $val )
{
// if it's not one of the two primary keys, push it to the array
if ( ! in_array($key, $all_primary_keys) )
{
$all_rows[ $s_id ][ $l_id ][ $key ] = $val;
}
}
}
#3
0
Is there a reason the below wouldn't work?
下面这句话有什么原因不能用吗?
$results = array();
while($row = $qry->fetch_assoc()){
$results[$row['site_id']][$row['language_id']] = array(
'name' => $row['name'],
'description' => $row['description']
);
}
#4
0
Here are two simple functions to solve your problem. I don't put any example as I have used your data and the same function name and arguments.
这里有两个简单的函数来解决你的问题。我没有给出任何例子,因为我使用了您的数据和相同的函数名和参数。
The first one takes profit of pointers to solve the first step of the problem:
第一步是利用指针来解决问题的第一步:
function nestByKeyNames($rows, $aKeys) {
$tab=Array();
foreach ($rows as &$v) {
// calculate the pointer position
$t=&$tab;
foreach ($aKeys as $v1) {
$t=&$t[$v[$v1]];
unset($v[$v1]);
}
// save the value
$t=$v;
}
return $tab;
}
This one uses a recursive algorithm and give the reverse output
这个算法使用递归算法并给出反向输出
function unNestByKeyNames($arrayRows, $aKeys){
$t=Array();
if (!count($aKeys)) return Array($arrayRows);
foreach ($arrayRows as $k=>&$v) {
$res=unNestByKeyNames($v, array_slice($aKeys,1));
foreach ($res as $k1=>$v1) $t[]=array_merge(Array($aKeys[0]=>$k), $v1);
}
return $t;
}
I have no suggestion about your SQL INSERT approach as long as you take care of sql injection, which I suppose might be the reason of your comment "validation has been removed for clarity"
我对SQL INSERT方法没有任何建议,只要您处理SQL注入,我想这可能就是您的注释“为了清晰而被删除”的原因。
#5
-1
There is no real method to what you wanting if you want to use the primary key you have to know the column name of the primary key hell you should not the columns your querying for. the best way to do it would be to use the AS
keyword in the MySQL Query
如果你想要使用主键,你必须知道主键的列名,你不应该查询你的列。最好的方法是在MySQL查询中使用AS关键字
SELECT primary as ID, ...
where primary is the column name of your primary key and now ID is your primary key in the result set.
选择primary作为ID,…主键是主键的列名,现在ID是结果集中的主键。
You can then just do the standard
然后你可以按照标准来做
$sortedResults = array();
while($row = $queryResult->fetch_assoc()){
$rowId = $row["ID"];
$sortedResults[$rowId] = $row;
}
If you don't know what the primary key is there i no reasonable way to obtain it there is a method to get the table columns and then you could go though them find the primary key save it then you have the primary key to do your while on but this would be one hell of an overhead on every query you make.
如果你不知道我有什么主键不合理的方式获得它有一个方法来获取表列,然后你可以尽管他们找到主键保存然后你有主键,但这将是一个地狱的开销在每个查询。
#1
5
This was trickier than I first imagined but I believe I have a messy solution.
这比我最初想象的要棘手,但我相信我有一个混乱的解决方案。
First of all, this is the data I am working with. dumpr
is a custom function that formats var_dump
better.
首先,这是我正在处理的数据。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);
Here is the zip and unzip functions:
这里是zip和unzip功能:
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;
}
And finally, here is the output. let me know if this is what you were asking for and if it worked OK on a larger data-set.
最后,这是输出。请让我知道这是否是您所要求的,以及它在更大的数据集上是否工作正常。
/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"
}
}
#2
0
Try this:
试试这个:
// initialize your array
$all_rows = array();
// loop through query results
while( $row = $qry->fetch_assoc() )
{
// temporarily store these vars for easy use later
$s_id = $row['site_id'];
$l_id = $row['language_id'];
// create an empty array based on site_id and language_id
$all_rows[ $s_id ][ $l_id ] = array();
// loop through all columns returned from query
foreach ( $row as $key => $val )
{
// if it's not one of the two primary keys, push it to the array
if ( ! in_array($key, $all_primary_keys) )
{
$all_rows[ $s_id ][ $l_id ][ $key ] = $val;
}
}
}
#3
0
Is there a reason the below wouldn't work?
下面这句话有什么原因不能用吗?
$results = array();
while($row = $qry->fetch_assoc()){
$results[$row['site_id']][$row['language_id']] = array(
'name' => $row['name'],
'description' => $row['description']
);
}
#4
0
Here are two simple functions to solve your problem. I don't put any example as I have used your data and the same function name and arguments.
这里有两个简单的函数来解决你的问题。我没有给出任何例子,因为我使用了您的数据和相同的函数名和参数。
The first one takes profit of pointers to solve the first step of the problem:
第一步是利用指针来解决问题的第一步:
function nestByKeyNames($rows, $aKeys) {
$tab=Array();
foreach ($rows as &$v) {
// calculate the pointer position
$t=&$tab;
foreach ($aKeys as $v1) {
$t=&$t[$v[$v1]];
unset($v[$v1]);
}
// save the value
$t=$v;
}
return $tab;
}
This one uses a recursive algorithm and give the reverse output
这个算法使用递归算法并给出反向输出
function unNestByKeyNames($arrayRows, $aKeys){
$t=Array();
if (!count($aKeys)) return Array($arrayRows);
foreach ($arrayRows as $k=>&$v) {
$res=unNestByKeyNames($v, array_slice($aKeys,1));
foreach ($res as $k1=>$v1) $t[]=array_merge(Array($aKeys[0]=>$k), $v1);
}
return $t;
}
I have no suggestion about your SQL INSERT approach as long as you take care of sql injection, which I suppose might be the reason of your comment "validation has been removed for clarity"
我对SQL INSERT方法没有任何建议,只要您处理SQL注入,我想这可能就是您的注释“为了清晰而被删除”的原因。
#5
-1
There is no real method to what you wanting if you want to use the primary key you have to know the column name of the primary key hell you should not the columns your querying for. the best way to do it would be to use the AS
keyword in the MySQL Query
如果你想要使用主键,你必须知道主键的列名,你不应该查询你的列。最好的方法是在MySQL查询中使用AS关键字
SELECT primary as ID, ...
where primary is the column name of your primary key and now ID is your primary key in the result set.
选择primary作为ID,…主键是主键的列名,现在ID是结果集中的主键。
You can then just do the standard
然后你可以按照标准来做
$sortedResults = array();
while($row = $queryResult->fetch_assoc()){
$rowId = $row["ID"];
$sortedResults[$rowId] = $row;
}
If you don't know what the primary key is there i no reasonable way to obtain it there is a method to get the table columns and then you could go though them find the primary key save it then you have the primary key to do your while on but this would be one hell of an overhead on every query you make.
如果你不知道我有什么主键不合理的方式获得它有一个方法来获取表列,然后你可以尽管他们找到主键保存然后你有主键,但这将是一个地狱的开销在每个查询。