Create dynamically named variables based on array keys - php

I have a multidimensional array and I want to create new variables based on the keys.
I have written this code, but it returns NULL:
$a = array("test" => array("a", "b", "c"));
foreach($a as $key => $value){
if(is_array($value)){
$i = 0;
foreach($value as $v){
$i++;
$$key[$i] = $v;
}
}
}
var_dump($test);
?>
Where is the problem?

Make that:
${$key}[$i] = $v;
$$key[$i] means "the variable whose name is $key[$i]".
${$key}[$i] means "position $i from the variable whose name is $key".
Also, it would be nice if you could initialize that $test array, so you won't get notices. Add the following before the second foreach:
$$key = array();

+1 to #Radu's answer, but you should also think about if these solutions would work for you:
$a = array("test" => array("a", "b", "c"));
foreach($a as $key => $value){
if(is_array($value)){
$$key = array_values($value);
}
}
var_dump($test);
Or:
$a = array("test" => array("a", "b", "c"));
extract($a);
var_dump($test);
See: array_values(), extract().

$$key[$i] tries to get the variable whose name matches the value of $key[$i]. You could get a reference to $$key first, and then add an item to that reference:
$a = array("test" => array("a", "b", "c"));
foreach($a as $key => $value){
if(is_array($value)){
$i = 0;
foreach($value as $v){
$i++;
$x = & $$key;
$x[$i] = $v;
}
}
}
var_dump($test);
?>
[edit]
But I see, I'm somewhat slow in testing and writing an answer, since another good answer has been posted minutes ago. Still keeping this, since it uses a different and not much more complex approach.

Related

PHP/MYSQL Replace text of keys in array of dictionaries

I have a MYSQL query that fetches an array of dictionaries or results which are returned via JSON in an api. In some cases, I would like to change the name of the dictionary keys in the results array.
For example, in the following case:
$var = '[{"player":"Tiger Woods"},{"player":"Gary Player"}]';
I would like to change it to:
$var = '[{"golfer":"Tiger Woods"},{"golfer":"Gary Player"}]'
It is not practical in this case to change the mysql query so I'd just like to replace the word "player" with the word "golfer" for the keys without disturbing the values.
In the above example, I would not want to change Gary Player's name so just using str_replace does not seem like it would work.
Is there a way to change all of the keys from "player" to "golfer" without changing any of the values?
Here is the snippet you can use
$var = '[{"player":"Tiger Woods"},{"player":"Gary Player"}]';
// json decode the json string
$temp = json_decode($var, true);
$temp = array_map(function($item){
// combining key and values
return array_combine(['golfer'], $item);
}, $temp);
print_r($temp);
// or echo json_encode($temp);
Demo.
Some argue that foreach is fastest,
foreach($temp as $k => &$v){
$v = array_combine(['golfer'], $v);
}
print_r($temp);
Demo.
Little hardcoded if more than one keys in single array,
foreach ($temp as $k => &$v){
$v['golfer'] = $v['player'];
unset($v['player']);
}
print_r($temp);
Demo.
Using recursion
function custom($arr, $newKey, $oldKey)
{
// if the value is not an array, then you have reached the deepest
// point of the branch, so return the value
if (!is_array($arr)) {
return $arr;
}
$result = []; // empty array to hold copy of subject
foreach ($arr as $key => $value) {
// replace the key with the new key only if it is the old key
$key = ($key === $oldKey) ? $newKey : $key;
// add the value with the recursive call
$result[$key] = custom($value, $newKey, $oldKey);
}
return $result;
}
$var = '[{"player":"Tiger Woods"},{"player":"Gary Player"}]';
$temp = json_decode($var, true);
$temp = replaceKey($temp, 'golfer', 'player');
print_r($temp);
Demo & source.
Using json way,
function json_change_key($arr, $oldkey, $newkey) {
$json = str_replace('"'.$oldkey.'":', '"'.$newkey.'":', json_encode($arr));
return json_decode($json, true);
}
$temp = json_change_key($temp, 'player', 'golfer');
print_r($temp);
Demo
If you want multiple key replace, here is the trick,
$var = '[{"player":"Tiger Woods", "wins":"10","losses":"3"},{"player":"Gary Player","wins":"7", "losses":6}]';
$temp = json_decode($var, true);
function recursive_change_key($arr, $set)
{
if (is_array($arr) && is_array($set)) {
$newArr = [];
foreach ($arr as $k => $v) {
$key = array_key_exists($k, $set) ? $set[$k] : $k;
$newArr[$key] = is_array($v) ? recursive_change_key($v, $set) : $v;
}
return $newArr;
}
return $arr;
}
$set = [
"player" => "golfers",
"wins" => "victories",
"losses" => "defeats"
];
$temp = recursive_change_key($temp, $set);
print_r($temp);
Demo.
$a = '[{"player":"Tiger Woods"},{"player":"Gary Player"}]';
$array = json_decode($a, true);
foreach($array as $key=>$value){
if(array_keys($value)[0] === "player"){
$array[$key] = ["golfer" => array_values($value)[0]];
};
}
echo json_encode($array);
you can write the value of the key to a new key and then delete the old.
renaming a key called "a" to "b", while keeping the value.
var json = {
"a" : "one"
}
json["b"] = json["a"];
delete json["a"];
for your example, just use this with a loop.
source: https://sciter.com/forums/topic/how-to-rename-the-key-of-json/

Using foreach on multidimensinal arrays

I tried to use a foreach loop on a multi-dimensional array, and found out that it didn't exactly worked out the way that I expected. Is there a foreach loop for multi-dimensional arrays, or another way to do this?
$array[0][0] = "a";
$array[0][1] = "b";
$array[0][2] = "c";
foreach($array as $a) {
echo $a."<br>";
}
Result:
Nothing
Needed Result:
a
b
c
You could also try this:
foreach($array[0] as $key => $value){
echo $value . "<br>":
}
$array in this code you're accessing the key of 0,0,0 so it will not print it.
$array[0] in this code you're both accessing key 0,1,2 and the values a,b and c
You need two loops. One to loop the first array, and one to loop the inner one.
foreach($array as $key) {
foreach($key as $val) {
echo $val;
}
}
Try nesting another foreach...
$array[0][0] = "a";
$array[0][1] = "b";
$array[0][2] = "c";
foreach($array as $a) {
foreach($a as $val){
echo $val."<br>";
}
}
It is because $a is still an array. If you use print_r() you will see this:
foreach($array as $a) {
print_r($a);
}
Result:
Array
(
[0] => a
[1] => b
[2] => c
)
To combat the nested array you have to run a second foreach() loop to get the values:
foreach($array as $a) {
foreach($a as $value){ // loop through second array
echo $value . "</ br>";
}
}
well since no one else has mentioned it:
<?php
$array[0][0] = "a";
$array[0][1] = "b";
$array[0][2] = "c";
echo implode('<br>',$array[0]);
http://codepad.viper-7.com/SC9PLI

Echo selected values from an associate array

i dont want to echo the last two values in an associative array, couldn's figure it out, please help.
foreach($_POST as $key => $value){
echo $value;
}
This echoes all the values, i want to echo all but the last 2.
Just count the loops and dont print the value in the last two loops.
$i = 0;
foreach($_POST as $key => $value) {
$i++;
if($i != count($_POST) && $i != count($_POST)-1) {
echo $value;
}
}
It should work to slice the array before you loop it.
<?php
$newArray = array_slice( $_POST, 0, count($_POST)-2);
foreach( $newArray AS $key => $value ) {
echo $value;
}
If you want to keep your $key value, then set the 4th parameter to true to "preserve keys":
http://php.net/manual/en/function.array-slice.php
Maybe this is just an exercise, but I do want to note, in addition, that relying on the exact order of your POST'd elements sounds like a bad design idea that could lead to future problems.
I'd rather do this:
$a = array('a' => 'q','s' => 'w','d' => 'e','f' => 'r');
$arr_count = count($a) - 2;
$i = 1;
foreach($a as $k => $val){
echo $k.' - '.$val.PHP_EOL;
if ($i == $arr_count) break;
$i++;
}
Another alternative solution:
<?php
$tot=count($_POST)-2;
while ($tot--) {
// you can also retrieve the key using key($_POST);
echo current($_POST);
next($_POST);
}

Append to end of associative array in PHP

I have an array which is defined as $array[colname]. For each value in $array[colname], I would like to append a piece of text to the end. The value already inside is string and I will append a string as well.
There are at least two possibilities
Edit the array in place:
foreach($a as &$v) {
$v .= 'APPENDED';
}
or
foreach($a as $k => $v) {
$a[$k] = $v . 'APPENDED';
}
Create a new array by mapping the old values to their new values:
$appended_array = array_map(function($v) { return $v . 'APPENDED'; }, $a);
Like this? You can easily iterate throug arrays
Here are the docs: http://php.net/manual/en/control-structures.foreach.php
Tip: Next time you should search on google and php.net because most default stuff are documented and in your question you used the right keywords that you needed to find it yourself
<?php
//Could write this shorter
$array = array();
$array['column1'] = 'value1';
$array['column2'] = 'value2';
//This is the short way
//http://php.net/manual/en/language.types.array.php
$array = array('column1' => 'value1', 'column2' => 'value2');
//Iterate throug every value in $array (That is every $array[colname])
//The & charachter before the $value means pass-by-reference you should do some research to understand this ;)
//foreach($array['colname'] as &$value) { for a single column with multiple values in it
foreach($array as &$value) {
// .= is the same as $value = $value . 'append'
// This way we append the text
$value .= 'append';
}
//Outputs all values in $array
print_r($array());
?>
You can use array_walk like below:
<?php
$fruits = array("d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple");
function test_alter(&$item1, $key, $string)
{
$item1 = "$item1 : $string";
}
array_walk($fruits, 'test_alter', 'fruit');
echo "... and after:\n";
array_walk($fruits, 'test_print');
?>
Output will be like this:
... and after:
d. lemon:fruit
a. orange:fruit
b. banana:fruit
c. apple:fruit
for more info:http://php.net/manual/en/function.array-walk.php
Here's the tested solution provided array matches to your stucture
<?php
$array = array();
$array['c1'] = array(1=>'data1', 2=>'data2', 3=>'data3', 4=>'data4');
$array['c2'] = array("d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple");
echo '<pre> Original Array : <br/>';
print_r($array);
foreach($array as $key=>$value)
{
foreach($value as $sub_key=>$sub_value)
{
$textToAppend = '_AppendedMe';
echo '<br/> brfore : '.$value[$sub_key];
$sub_value .= $textToAppend;
$array[$key][$sub_key]=$sub_value;
echo '<br/> after : '.$value[$sub_key];
}
}
echo '<br/> Array after : ';
print_r($array);
echo '</pre>';
?>

foreach access the index or an associative array

I have the following code snippet.
$items['A'] = "Test";
$items['B'] = "Test";
$items['C'] = "Test";
$items['D'] = "Test";
$index = 0;
foreach($items as $key => $value)
{
echo "$index is a $key containing $value\n";
$index++;
}
Expected output:
0 is a A containing Test
1 is a B containing Test
2 is a C containing Test
3 is a D containing Test
Is there a way to leave out the $index variable?
Your $index variable there kind of misleading. That number isn't the index, your "A", "B", "C", "D" keys are. You can still access the data through the numbered index $index[1], but that's really not the point. If you really want to keep the numbered index, I'd almost restructure the data:
$items[] = array("A", "Test");
$items[] = array("B", "Test");
$items[] = array("C", "Test");
$items[] = array("D", "Test");
foreach($items as $key => $value) {
echo $key.' is a '.$value[0].' containing '.$value[1];
}
You can do this:
$items[A] = "Test";
$items[B] = "Test";
$items[C] = "Test";
$items[D] = "Test";
for($i=0;$i<count($items);$i++)
{
list($key,$value) = each($items[$i]);
echo "$i $key contains $value";
}
I haven't done that before, but in theory it should work.
Be careful how you're defining your keys there. While your example works, it might not always:
$myArr = array();
$myArr[A] = "a"; // "A" is assumed.
echo $myArr['A']; // "a" - this is expected.
define ('A', 'aye');
$myArr2 = array();
$myArr2[A] = "a"; // A is a constant
echo $myArr['A']; // error, no key.
print_r($myArr);
// Array
// (
// [aye] => a
// )

Categories