Setting value in Nested Php Array - php

Hi I'm trying to loop through a array and set a keys value. Very basic question.
The Code I tried is below.
http://pastebin.com/d3ddab156
<?php
$testArray = array("bob1" => array( 'name' => "bob1", 'setTest' => '2'));
foreach($testArray as $item)
{
$item['setTest'] = 'bob';
}
print_r($testArray);
I imagine I'm missing something stupid here and it is going to be a D'oh! moment for me. What is wrong with it?
Thanks.

You do:
$testArray = array("bob1" => array( 'name' => "bob1", 'setTest' => '2'));
foreach($testArray as $item)
{
$item['setTest'] = 'bob';
}
print_r($testArray);
$item is a copy. You change the copy, not the real array. Try this:
$testArray = array("bob1" => array( 'name' => "bob1", 'setTest' => '2'));
foreach($testArray as $key => $item)
{
$testArray[$key]['setTest'] = 'bob';
}
print_r($testArray);

Or, if you have a lot of data in the array and want to avoid creating a complete copy of each element over every iteration, simply iterate over each element as a reference. Then only a reference to that item is created i memory and you can directly manipulate the array element by using $item:
$testArray = array("bob1" => array( 'name' => "bob1", 'setTest' => '2'));
foreach($testArray as &$item)
{
$item['setTest'] = 'bob';
}
print_r($testArray);
NOTE: be sure to unset $item after the loop so you don't inadvertantly modify the array later by using that variable name.

Related

How can I remove all data in an array - PHP

I'm trying to delete all the data in this array. I'm beginer
$data = array(
['id' => 1, 'name' => 'Alex'],
['id' => 2, 'name' => 'Max'],
['id' => 3, 'name' => 'George']
);
I'm using this code to do it, but it doesn't work :(
foreach ($data as $item) {
unset($item);
}
When you want to clear the complete array, why not using unset($data)?
Your code does not work they way as you expect it, because in your loop you are defining a new variable $item. You are then unsetting this variable $item which has no effect on original the values of your $data array.
If you want to use a loop you need to define it like that:
foreach ($data as $index => $item) {
unset($data[$index]);
}
This clears all values from $data but not unsetting the $data array itself.
A more efficient way compared to the loop would be to just assign a empty array to $data like:
$data = [];

Loop over one array as if it was a multidimensional array

I have an array like:
$array = array(
'name' => 'Humphrey',
'email' => 'humphrey#wilkins.com
);
This is retrieved through a function that gets from the database. If there is more than one result retrieved, it looks like:
$array = array(
[0] => array(
'name' => 'Humphrey1',
'email' => 'humphrey1#wilkins.com'
),
[1] => array(
'name' => 'Humphrey2',
'email' => 'humphrey2#wilkins.com'
)
);
If the second is returned, I can do a simple foreach($array as $key => $person), but if there is only one result returned (the first example), I can't run a foreach on this as I need to access like: $person['name'] within the foreach loop.
Is there any way to make the one result believe its a multidimensional array?
Try this :
if(!is_array($array[0])) {
$new_array[] = $array;
$array = $new_array;
}
I would highly recommended making your data's structure the same regardless of how many elements are returned. It will help log terms and this will have to be done anywhere that function is called which seems like a waste.
You can check if a key exists and do some logic based on that condition.
if(array_key_exists("name", $array){
//There is one result
$array['name']; //...
} else {
//More then one
foreach($array as $k => $v){
//Do logic
}
}
You will have the keys in the first instance in the second yours keys would be the index.
Based on this, try:
function isAssoc(array $arr)
{
if (array() === $arr) return false;
return array_keys($arr) !== range(0, count($arr) - 1);
}
if(isAssoc($array)){
$array[] = $array;
}
First check if the array key 'name' exists in the given array.
If it does, then it isn't a multi-dimensional array.
Here's how you can make it multi-dimensional:
if(array_key_exists("name",$array))
{
$array = array($array);
}
Now you can loop through the array assuming it's a multidimensional array.
foreach($array as $key => $person)
{
$name = $person['name'];
echo $name;
}
The reason of this is probably because you use either fetch() or fetchAll() on your db. Anyway there are solutions that uses some tricks like:
$arr = !is_array($arr[0]) ? $arr : $arr[0];
or
is_array($arr[0]) && ($arr = $arr[0]);
but there is other option with array_walk_recursive()
$array = array(
array(
'name' => 'Humphrey1',
'email' => 'humphrey1#wilkins.com'
),
array(
'name' => 'Humphrey2',
'email' => 'humphrey2#wilkins.com'
)
);
$array2 = array(
'name' => 'Humphrey2',
'email' => 'humphrey2#wilkins.com'
);
$print = function ($item, $key) {
echo $key . $item .'<br>';
};
array_walk_recursive($array, $print);
array_walk_recursive($array2, $print);

Hierarchical data into array

I need some logic for the following problem, but can't get my head around it. Basically I have some data like the following array
array(
array('name' => 'Test1',
'hierarchy'=> '1'),
array('name' => 'Test2',
'hierarchy'=> '1.1'),
array('name' => 'Test3',
'hierarchy'=> '1.2'),
array('name' => 'Test4',
'hierarchy'=> '1.2.1')
)
Now I would like to output an array in such a way that
$array[1] = 'Test1';
$array[1][2][1] = 'Test4';
Tried dynamic variable naming and dynamically creating multidimensional arrays, but both dont seem to work.
That's not possible.
For $array[1] = 'Test1'; $array[1] needs to be a string, but for $array[1][2][1] = 'Test4'; it needs to be an array.
You could do something like this:
$array[1]['text'] = 'Test1';
$array[1][2][1]['text'] = 'Test4';
Here's code for that:
$result = array();
foreach ($input as $entry)
{
$path_components = explode('.', $entry['hierarchy']);
$pointer =& $result;
foreach ($path_components as $path_component)
$pointer =& $pointer[$path_component];
$pointer['text'] = $entry['name'];
unset($pointer);
}
If you don't absolutely need an array, you can create a class and extend ArrayClass or if you need only the array access, you can also implement ArrayAccess.
From there, you can parse through your data and return the required values for your application.

if one array element similar to request variable, then how to fetch another elements of array

I am asking Similar question compare request values to array - it doesn't work to me, my scenario is totally different
$mkt = array(
array(
'title' => "Photos",
'iconlink' => "http://example.com/xyz.png",
'pkg' => 'test'
),
array(
'title' => "code",
'iconlink' => "http://example.com/xyz.png",
'pkg' => 'main'
),
array(
'title' => "code",
'iconlink' => "http://example.com/xyz.png",
'pkg' => 'main'
));
I am having logic issue in this problem, problem is i am getting value via $_REQUEST variable and then i compare this request value to array pkg element. If comparison is true then i want to get another elements except to matched one. In this as suggested, i am using unset to remove the key of element which is matched and all array point to new variable, it working but not for first element of array, it shows null when i compare request variable to first element of array:
$mkt = array();
$newArray = $mkt;
foreach ($newArray as $key => $value ) {
if (in_array($pn, $mkt, true)) {
unset($newArray[$key]);
}
}
$rand_ad = array_rand( $newArray, 1 );
echo json_encode( $newArray[$rand_ad] );
Please have a look on this issue very grateful to me.
Loop in each value, if $pn is equal with that loop's pkg then unset than unset that element:
$pn = 'main';
$newArray = $mkt;
foreach ($newArray as $key => $val) {
if ($pn == $val['pkg']) {
unset($newArray[$key]);
}
}
echo json_encode($newArray);
// [{"title":"Photos","iconlink":"http:\/\/example.com\/xyz.png","pkg":"test"}]

Exploding and replacing one array field

So, I have an array that, for unrelated reasons, has one imploded field in itself. Now, I'm interested in exploding the string in that field, and replacing that field with the results of the blast. I kinda-sorta have a working solution here, but it looks clunky, and I'm interested in something more efficient. Or at least aesthetically pleasing.
Example array:
$items = array(
'name' => 'shirt',
'kind' => 'blue|long|L',
'price' => 10,
'amount' => 5);
And the goal is to replace the 'kind' field with 'color', 'lenght', 'size' fields.
So far I've got:
$attribs = array('color', 'lenght', 'size'); // future indices
$temp = explode("|", $items['kind']); // exploding the field
foreach ($items as $key => $value) { // iterating through old array
if ($key == 'kind') {
foreach ($temp as $k => $v) { // iterating through exploded array
$new_items[$attribs[$k]] = $v; // assigning new array, exploded values
}
}
else $new_items[$key] = $value; // assigning new array, untouched values
}
This should (I'm writing by heart, don't have the access to my own code, and I can't verify the one I just wrote... so if there's any errors, I apologize) result in a new array, that looks something like this:
$new_items = array(
'name' => 'shirt',
'color' => 'blue',
'lenght' => 'long',
'size' => 'L',
'price' => 10,
'amount' => 5);
I could, for instance, just append those values to the $items array and unset($items['kind']), but that would throw the order out of whack, and I kinda need it for subsequent foreach loops.
So, is there an easier way to do it?
EDIT:
(Reply to Visage and Ignacio - since reply messes the code up)
If I call one in a foreach loop, it calls them in a specific order. If I just append, I mess with the order I need for a table display. I'd have to complicate the display code, which relies on a set way I get the initial data.
Currently, I display data with (or equivalent):
foreach($new_items as $v) echo "<td>$v</td>\n";
If I just append, I'd have to do something like:
echo "<td>$new_items['name']</td>\n";
foreach ($attribs as $v) echo "<td>$new_items[$v]</td>\n";
echo "<td>$new_items['price']</td>\n";
echo "<td>$new_items['amount']</td>\n";
Associative arrays generally should not depend on order. I would consider modifying the later code to just index the array directly and forgo the loop.
Try this:
$items = array( 'name' => 'shirt', 'kind' => 'blue|long|L', 'price' => 10, 'amount' => 5);
list($items['color'], $items['lenght'], $items['size'])=explode("|",$items['kind']);
unset $items['kind'];
I've not tested it but it should work.
Associative arrays do not have an order, so you can just unset the keys you no longer want and then simply assign the new values to new keys.
one way
$items = array(
'name' => 'shirt',
'kind' => 'blue|long|L',
'price' => 10,
'amount' => 5);
$attribs = array('color', 'lenght', 'size');
$temp = explode("|", $items['kind']);
$s = array_combine($attribs,$temp);
unset($items["kind"]);
print_r( array_merge( $items, $s) );
This should retain the ordering because it splits the keys and values into two numerically ordered arrays and combines them at the end. It isn't more efficient, but the code is easier to read.
$kind_keys = array('color', 'length', 'size');
$kind_values = explode("|", $items['kind']);
$keys = array_keys($items);
$values = array_values($items);
$index = array_search('kind', $keys);
// Put the new keys/values in:
array_splice($keys, $index, 1, $kind_keys);
array_splice($values, $index, 1, $kind_values);
// combine the result into a new array:
$result = array_combine($keys, $values));

Categories