I am having a problem where a routine (that I cannot modify) is returning me either a 3 nested array -or- a 2 nested array. The key values are never the same, however, I'd like to normalize the nesting so that I can make the 2 nested array 3 levels deep every time to avoid "Notice: Undefined index:" errors. Or if possible, have a routine to count the number of levels deep the array is so I can code accordingly.
You can use isset() to determine if a particular level is present in the array. If not, add it.
function get_depth($arr) {
foreach ( $arr as $arr2 ) {
if ( is_array($arr2) ) {
return 1+get_depth($arr2);
}
break;
}
return 1;
}
Well, this answer is really going to depend on what you're doing. Why not simply check to see if the nested array exists?
if (isset($val[3][2])) {
....
}
Related
Say that I have an associative array of different types of fruits in baskets and the amount in each basket ('Banana'=>50 and etc) and I need to know how many of each type of fruit there is, but I don't know the possible types of fruit before I start the loop that generates the array. This may result in duplicate entries such as:
$baskets = array(
"Apple"=>"35",
"Banana"=>"37",
"Apple"=>"43"
);
Question A: Is it even possible to make the second "Apple" entry or will it result in an error?
The answer was: Not possible, it would overwrite the first one with 43
Question B1: Assuming that the answer to A is "It's possible", how do I merge the two so that $baskets becomes ("Apple"=>"78","Banana"=>"37")?
Question B2: Assuming that the answer to A is "Not possible", how do I go about figuring out if there's already apples in the array and add the amount to the entry rather than attempting to add it as a new point in the array?
An answer to B2 will obviously make B1 obsolete even if A is "possible".
If neither B1 nor B2 are possible, then is there some other way that I can keep track of the amount of each type of fruit as I loop through the baskets?
Thanks for all of the helpful answers.
Q A: No
Q B:
if(isset($baskets["apple"]))
{
$baskets["apple"] = $baskets["apple"] + VALUE
}
You will never get the duplicate keys in an array, there can only be unique keys. You will be only overwriting values for the key of duplicate fruits.
Answer B: due to the reason mentioned above, you will have to check in your loop whether the key exists in your resulting array, and if it does, add the new value to the existing one, otherwise store the value under this key.
Answer to B1: see answer to A.
Answer to B2: array_key_exists or isset
The algorithm depends on the way your data is stored. Maybe there's a more clever way possible.
Question A: Is it even possible to make the second "Apple" entry or will it result in an error?
No, would it be so hard to try it out?
$basket['apple']=35;
$basket['apple']=43;
print $basket['apple']; // the output will be 43
The second assignment overwrites the former.
how do I merge the two
You could simply do this:
$basket['apple']+=35;
$basket['apple']+=43;
print $basket['apple'];
The problem with this is that the first time you reference an entry in the array, a PHP warning will be triggerred as it does not yet exist. While you should have your error reporting disabled (but error logging enabled) on your production system, this causes performance and support issues, hence a better solution is....
function add_to($basket, $product, $amount)
{
if (isset($basket[$product])) {
$basket[$product]+=$amount;
} else {
$basket[$product]=$amount;
}
}
add_to($basket, 'apple', 35);
add_to($basket, 'apple', 43);
print $basket['apple']; // output will be 78
It is not possible to have the same key ('Apple') more then once in an associative array. If you are looping through and come across 'Apple' twice, the second entry will override the first:
array['Apple'] = 35
array['Banana']= 37
array['Apple' = 43
would result in an array:
( 'Apple' => 43, 'Banana' = 37 )
See Labradorcode's answer for the correct implementation and don't forget to cast your string values as ints!
EDIT to elaborate on his answer
for($i = 0; i < count(list_of_fruits){
if(!array_key_exists($fruit, $basket){
$basket[$fruit] = 0;
}
$basket[$fruit] = $basket[$fruit] + (int)$num_fruits;
something like that
When working with existing code, it takes one array and places it into another in the fashion shown below.
I believe the empty brackets are the same thing as simply pushing it and appending it to the first available index.
$g['DATA'][] = $p;
After this is done, I have my own array that I would like to append to this as well. I tried using array_merge() with $g['DATA'][]as a parameter, but this is invalid for obvious reasons.
My only thought is to create a foreach loop counter so I can figure out the actual index it created, however I have to assume there is some cleaner way to do this?
Just simply use the count() of your $g["DATA"] array as index and then you can merge it like this:
$g['DATA'][count($g["DATA"])-1] = array_merge($g['DATA'][count($g["DATA"])-1], $ownArray);
//^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
// -1 Because an array is based index 0 -> means count() - 1 = last key
I'm trying to access an array within another array (basically, a two dimensional array). However, the usual way of doing this ($myarray[0][0]) doesn't work for me.
The reason is because I want to create a recursive function which, in each call, should dive deeper and deeper into a array (like, on first call it should look at $myarray[0], on second call it should look at $myarray[0][0] and so on).
Is there any alternative way of accessing an array within array?
Thanks.
Traverse the array by passing always a subarray of it to the recursive function.
function f(array &$arr)
{
// Some business logic ...
// Let's go into $arr[0]
if(is_array($arr[0]))
f($arr[0]);
}
f($myarray);
I have PHP $_SESSION arrays that have an undefined amount of elements. Is it possible to initialise all the values to 0, or do I have to check whether the value is NULL and then set to 0 every time I check a value?
Edit: I'm sorry for the vagueness of my question.
I have an undefined amount of levels, and I'd like to store all the scores of each level in that array. Currently my amount of levels is fixed, so I am currently just writing:
$_SESSION['totals'] = array(0,0,0,0,0);
And then when adding manipulating the data, I simply increment/add a certain amount to that element.
Now I'd prefer to have the same ease of directly incrementing/adding values to certain elements without needing to check whether a value is NULL or something like that...
Edit 2: edited my code as follows:
$_SESSION['totals'] = array();
if(array_key_exists($row['level']-1,$_SESSION['totals'])){
$_SESSION['totals'][$row['level']-1]++;
}else{
$_SESSION['totals'][$row['level']-1] = 1;
}
And it seems to work. Thanks fellas!
You can use array_fill_keys function to fill an array with specified value for defined keys:
$keys = array('foo', 'bar', 'baz');
$output = array_fill_keys($keys, 0);
Defining an array with initial values is defining an array with a length. This does not prevent you from adding or removing elements from the array:
// initial array
$myArray = [0, 0, 0, 0];
print_r($myArray); // would output Array ( [0] => 0 [1] => 0 [2] => 0 [3] => 0)
$myArray[] = 1;
print_r($myArray); // would output Array ( [0] => 0 [1] => 0 [2] => 0 [3] => 0 [4] => 1 )
$_SESSION contains only what you put into it. Just make sure you add 0 instead of null the first time you add something.
If you need to do this later, I think your design might be bad. But anyway, $_SESSION is like a normal array, so you can just use PHP's array function to traverse the array and check or change each value.
PHP arrays aren't really arrays you might know from other languages. They really are more like linked lists with hash access.
What this means is: You either know all the string array indices you want to use, and either make sure they exist, or you check their existence every time you access them which might fail.
For numeric indices, the same thing applies. You might have an array with indices 1, 2 and 4 present, but if you run over it with only a for loop, you will trigger a notice when accessing the nonexistant element 3.
Use foreach loops whenever you want to iterate arrays. Check with isset() whenever you want to document that the array value might not be present. Don't do it if you know or assume that the array element MUST be present - if not, you get the notice as a reminder that your code is working on a data structure that is NOT what you thought it is. Which actually is a good thing. Then fix it. :)
Your best bet would be to abstract your session stuff by creating facade methods, or getters and setters around the session variables rather than access them directly. This way you can return a default value if the one you're after doesn't exist.
I've used array_key_exists() to check if the index is set. If it is not, I display 0 or add store a certain value in that field, else I show the value of that index or add certain value to that field.
Credit to Sven for bringing that up.
to check what u have in your sessions, loop tru it. not sure if this is what u are asking.
foreach($_SESSION as $x=>$y)
{
if(empty($x)) { //do something }
}
I'm trying to solve this problem where I have a unique array of values within a specific range. Take this scenario: Generate a fixed value array (90) with unique entries. If you find a duplicate, remove, reindex, and fill the void. I'm running into the problem that conditional statements do not allow you to interact with an array outside of it's scope. I'm aware of array_unique but it doesn't refill those gaps, just makes them. How do I refill those gaps?
EDIT: This was a noobish question about scoping. A simple while loop demonstrated that if conditional statements can modify variables outside of it's scope.
?>
Not sure if this will help but you can always reiterate over the array once the duplicateds have been removed and reindex it if that is what you mean?
Making sure I understand this - you don't care for the array key elements?
You could still use array_unique();
// $array(); is already defined with elements in it
$temp_array = array_unique($array);
if ( !empty ( $temp_array ) ) {
unset($array);
$array = array();
foreach ( $temp_array as $t ) {
array_push($array, $t);
}
}
You'd probably want to put a clause in there stopping it if it goes over 90 elements.