How to get keys/values from an incomplete associative array? - php

I have this kind of array:
$a = array(
'one' => 'one',
'0' => '0',
'two' => 'two',
'three' => 'three',
'four'
);
as you can see it is an associative array BUT not all the keys have the value (take a look at the last).
My question is, how can i loop this kind of array to get key(if exists) and the respective value?
Thank you!

The string 'four' in your example is not a key but a value. The corresponding key will be 1. This happens because PHP converts the string key '0' to numeric key 0 and for the value 'four' it uses the next numeric key which will be 1.
Reference:
A key may be either an integer or a string. If a key is the standard
representation of an integer, it will be interpreted as such (i.e. "8"
will be interpreted as 8, while "08" will be interpreted as "08")
To have a key with no value you can use NULL as the value:
'four' => null
Similarly to have an empty key use null as key:
null => 'four'
And to loop over such an array you can use a foreach loop. To detect if a key/value is null or not you can use the isset function.

With var_dump($a); you see all keys and values:
array(5) {
["one"] => string(3) "one"
[0] => string(1) "0"
["two"] => string(3) "two"
["three"] => string(5) "three"
[1] => string(4) "four"
}

you can use the foreach construction:
foreach($a as $key=>$val){
// $key is a current key
// $val is tha current value associated
}

As described in PHP: Arrays
A key may be either an integer or a string. If a key is the standard representation of an integer, it will be interpreted as such (i.e. "8" will be interpreted as 8, while "08" will be interpreted as "08"). Floats in key are truncated to integer. The indexed and associative array types are the same type in PHP, which can both contain integer and string indices.
So you cannot distinguish key '0' and 0. And your last element is not a key, it is a value with auto incremental integer key 1. You can check with var_dump($a):
array(5) {
["one"]=>
string(3) "one"
[0]=>
string(1) "0"
["two"]=>
string(3) "two"
["three"]=>
string(5) "three"
[1]=>
string(4) "four"
}
If you can ensure all your keys do not start with digit, then you can just iterate the array as usual, and test the key using is_int.

Related

Understanding PHP arrays, specifically example given

I am new to PHP and arrays and am wanting to understand the following array. I would also like to learn how I would go about assigning values to two particular array elements in PHP, i.e.:
["_gravity_form_lead"]=> array(5) { [1]=> string(4) "1000" [3]=> string(6) "strips" [2]=> string(2) "rp" [5]=> string(0) "" [6]=> string(0) "" }
1) What is the correct notation to define this array?
2) For the two array elements that are "", i.e.
[5]=> string(0) "" [6]=> string(0) ""
In PHP, how would I go about assigning values to these two array elements, that are NULL?
Hope this makes you understand ,
$array_before = array('_gravity_form_lead' => array( '1000', "strips", "rp", '', ''));
echo '<pre>';
echo 'This what it looks after print_r'.'<br>';
print_r($array_before);
echo '</pre>';
I don't see anything different and special than its said in the documentation
http://php.net/manual/en/language.types.array.php
Anyway, the concrete situation is.
$_gravity_form_lead = array(1=>1000, 3=>'strips', 2=>'rp', 5=>'', 6=>'');
As said in the documentation
Creating/modifying with square bracket syntax ¶
An existing array can be modified by explicitly setting values in it.
This is done by assigning values to the array, specifying the key in brackets. The key can also be omitted, resulting in an empty pair of brackets ([]).
$arr[key] = value;
You do modify the ones you need with [ ]
In this particular case:
$_gravity_form_lead[5] = 'something';
$_gravity_form_lead[6] = 'something else';
In order you want to modify all empty strings, you can iterate through the array and modify. You have two options while iterating - using reference &, which will modify the existent one, or creating new array.
foreach ($_gravity_form_lead as &$val) {
if ($val == '') {
$val = 'something';
}
}
The output after doing this is
var_dump($_gravity_form_lead);
/*
* array (size=5)
1 => int 1000
3 => string 'strips' (length=6)
2 => string 'rp' (length=2)
5 => string 'something' (length=9)
6 => &string 'something' (length=9)
*/
It would be defined somewhat like,
$arrayName = array('_gravity_form_lead' => array( 1=>'1000', 3=>"strips", 2=>"rp", 5=>'', 6=>''));
/* assign null instead of '' */
$arrayName['_gravity_form_lead'][5] = NULL;
$arrayName['_gravity_form_lead'][6] = NULL;

Associative Array Key Casting Float String

In my code, I have generated an associative array with keys as floats, however the PHP documentation states that when they become key's in the array they are SUPPOSED to be cast to integers. Instead, they are being cast to strings (which is actually better for me so I'm not complaining).
The problem is that when I try to access these keys using a float as the key value, it casts only the floats with .5 to integers and creates a new entry in the array. Seems like peculiar behavior.
Example:
var_dump( $array );
Output:
array(9) {
[0] =>
int(0)
[1.25] =>
int(0)
[2.5] =>
int(0)
....}
When I try to access the value 2.5 like so,
array[2.5]++;
a new entry in the array is made at array[2]
However if I try to access the array at array[1.25]++;
I successfully add 1 to the value at key: 1.25
Any ideas?
I would just stick with strings all the time:
$a = array(
'0' => 0,
'1.25' => 0,
'2.5' => 0
);
$a['2.5']++;
echo $a['2.5'] . "\n";
var_dump($a);
Output is:
1
array(3) {
[0]=>
int(0)
["1.25"]=>
int(0)
["2.5"]=>
int(1)
}

Difference between functions: array_diff_ukey and array_diff_uassoc

Can someone please explain to me whats the difference between these 2 functions:
array_diff_ukey
array_diff_uassoc
They both take keys into the compare function, and based on those keys decide if the array element should be returned or not. I've checked the php manual, but to me they both seem to be doing the same thing...
array_diff_ukey returns those elements of the first array whose keys compare different to all keys in the second array (the semantics of the comparison being user-defined). The values associated with those keys do not play a part.
array_diff_uassoc is a "more inclusive" version of the above that also checks values: if a key in the first array compares equal to a key in the second array but the values are different, that element is also included in the result. In this case, comparison of values is not user-defined, but works as in array_diff: for two values to compare equal, their string representation must be identical.
Example, adapted from the PHP docs:
function key_compare_func($key1, $key2)
{
if ($key1 == $key2)
return 0;
else if ($key1 > $key2)
return 1;
else
return -1;
}
$array1 = array('blue' => 1, 'red' => 2, 'green' => "3", 'purple' => 4);
$array2 = array('green' => 3, 'blue' => 6, 'yellow' => 7, 'cyan' => 8);
var_dump(array_diff_ukey($array1, $array2, 'key_compare_func'));
var_dump(array_diff_uassoc($array1, $array2, 'key_compare_func'));
See it in action.
Here, array_diff_ukey will return the "red" and "purple" elements from $array1 because these keys do not compare equal to any of the keys in $array2. However array_diff_uassoc will also return the "blue" element, because even though that key exists in both arrays the associated values are different.
Note that the "green" element is not included in either result, despite the fact that the associated value is a string in $array1 and an integer in $array2.
From the manual:
array_diff — Computes the difference of arrays
array_diff_key — array_diff_key — Computes the difference of arrays using keys for comparison
array_diff_assoc — Computes the difference of arrays with additional index check
This additional index check means that not only the value must be the same, but also the key must be the same. So the difference between array_diff_ukey and array_diff_uassoc is that the latter checks both keys and values, while the first only checks the keys.
The addition of the u after diff_ means that you must supply a custom callback function instead of the default built-in function.
Example based on the manual (Fiddle)
<?php
header("Content-Type: text/plain");
$array1 = array('blue' => 1, 'red' => 2, 'green' => 3, 'black' => 0, 'purple' => 4);
$array2 = array('green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan' => 8, 'black' => 0);
var_dump(array_diff($array1, $array2));
var_dump(array_diff_key($array1, $array2));
var_dump(array_diff_assoc($array1, $array2));
?>
Output
array(4) {
["blue"]=>
int(1)
["red"]=>
int(2)
["green"]=>
int(3)
["purple"]=>
int(4)
}
array(2) {
["red"]=>
int(2)
["purple"]=>
int(4)
}
array(4) {
["blue"]=>
int(1)
["red"]=>
int(2)
["green"]=>
int(3)
["purple"]=>
int(4)
}

passing null as array_keys second parameter

PHP documentation states that the default value of array_keys second argument is NULL.
However, when passing NULL explicitly, array_keys does not seem to work properly.
Example:
code
$a = array(10=>'a', 11=>'b', 12=>'b', 13=>'c', 14=>'c', 15=>'b');
$keys = array_keys($a);
var_dump($keys); //Output 0
$keys = array_keys($a, null);
var_dump($keys); //Output 1
Output
array
0 => int 10
1 => int 11
2 => int 12
3 => int 13
4 => int 14
5 => int 15
array
empty
Question
I reckon it must be trying to find keys whose value is null.
Passing false or empty string produces the exact same behavior (obviously).
So, what is the default value?
Answer
xdazz answer is right. When inspecting the C code of this function, my first though was that this was a bad implementation at C level (and easily fixed by removing code)
But then I realized this is actually the intended behavior since they went to a lot of trouble to enable you to test for NULL values inside the array.
The default value is hard to explain here.
It is special case, the default value of second parameter is not actually the php's NULL, but the C level's NULL.
Dive into the source code:
PHP_FUNCTION(array_keys)
{
zval *input, /* Input array */
*search_value = NULL, /* Value to search for */
//....
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|zb", &input, &search_value, &strict) == FAILURE) {
return;
}
// ....
You could see, the default value is NULL for search_value, but if you specified the second parameter of array_keys, then after zend_parse_parameters, search_value will not be NULL.
I agree with xdazz. However, it seems that passing 0 works. Don't ask me how, though! (And, YMMV.)
$a = array(10=>'a', 'xaa'=>'b', 12=>'b', 13=>'c', 14=>'c', 15=>'b');
$keys = array_keys($a, 0);
var_dump($keys); //Output 0
Returns:
array(6) { [0]=> int(10) [1]=> string(3) "xaa" [2]=> int(12) [3]=> int(13) [4]=> int(14) [5]=> int(15) }
Since you're searching for null, there's no result to give back to you :)
It is hard to infer from PHP manual as to the use of search_value parameter. I needed to do try an example.
If the optional search_value is specified,
then only the keys for **that** value are returned.
Otherwise, all the keys from the input are returned.
It means that when search_value is specified in array_keys(), the values in the array (not keys) are searched against search_value. If match occurs, the key for that value in search_value is returned.
Example
<?
$foo = array('first' => 'my_first',
'second' => 'my_second',
'third' => 'my_third',
'fourth' => null);
$keys = array_keys($foo);
var_dump($keys); //Output 0
$keys = array_keys($foo, 'my_second');
var_dump($keys); //Output 1
$keys = array_keys($foo, null);
var_dump($keys); //Output 2
?>
Output
0:
array(4) {
[0]=>
string(5) "first"
[1]=>
string(6) "second"
[2]=>
string(5) "third"
[3]=>
string(6) "fourth"
}
1:
array(1) {
[0]=>
string(6) "second"
}
2:
array(1) {
[0]=>
string(6) "fourth"
}

array_merge strange behaviour

Look at this code:
$a = array('1'=>'1');
$b = array(''=>'');
var_dump(array_merge($a,$b));
the output seems really strange to me:
array(2) {
[0] =>
string(1) "1"
'' =>
string(0) ""
}
Ok, I've changed $a into this: $a = array('k'=>'v'); and the output became more predictable:
array(2) {
'k' =>
string(1) "v"
'' =>
string(0) ""
}
The question is: why the hell the key of the first element is 0 in the first example?
edit:
var_dump($a);
array(1) {
[1] =>
string(1) "1"
}
Values in the input array with numeric keys will be renumbered with incrementing keys starting from zero in the result array.
http://php.net/array_merge
Yes, it's an idiosyncrasy of PHP to treat numeric string values as numeric values in this case. You may want to use $a + $b instead.

Categories