How can I tell if array element, in foreach loop, has a key?
Some code:
function test($p_arr){
foreach ($p_arr as $key => $value){
// detect here if key 'came with the array' or not
}
}
$arr1['a'] = 10;
$arr2[] = 10;
$arr3[2] = 10;
test($arr1); // yes
test($arr2); // no
test($arr3); // yes
edit #1
I am aware that $arr2 also as an automated index-key. I need to know if it is automated or not.
edit #2
My use of it is simple.
In the function, I create a new array and use the $key as the new $key, if it was provided by the function call. or the $value as the new $key, if it was omitted in the function call.
I know that I can just force the use of key to each element, but in some parts of the code, the data structure itself is very dynamic* - and i'm trying to stay flexible as much as possible.
*code that create other code, that create ... and so on.
There is no difference between explicit keys and implicit keys generated via []. The [] doesn't mean "give this element no key", it means "use the next key for this element".
Every element has a key
$arr1['a'] = 10; // key is the string 'a'
$arr2[] = 10; // key is will be the integer zero
$arr3[2] = 10; // key is the integer 2
Edit
Perhaps it would be good to understand why you wish to know if the index is automated or not? It seems odd.
Every array created has to have a key, whether it's a integer or string as the key or index, without no index the PHP would have no way to interpret or even pull information from the array it's self.
$Var = array ("String","anotherstring","sdfhs","dlj");
the above array will automatically be generated with a numeric index starting from 0.
$Array = array();
$Array[] = "This is a string";
The above will push information into the array, as there has been no index or key specified. It will automatically be assigned with the closest numeric value to 0, which does not already exist in the array.
$Array = array();
$Array['key'] = "This is another string";
The above will push information into the array also, but as we have specified an index with a string representation rather an automatically assigned value.
So the answer to your question, if i'm reading this Correctly.
If your referring to check if the array values are specified by PHP/The Code prior to reading the array. There is no soundproof method, as everything would need to be assigned to the array before it has data. further more, if your only adding elements to the array with a string key, then yes. It is possible.
If your relying on automatically generated numeric values, or assigning your own numeric values. it's impossible to tell if PHP has assigned this automatically, or you have specified.
Related
I got values of column A and B from Excel by below php code
for($i=1;$i<=$arrayCount;$i++)
{
$col_A = array(trim($allDataInSheet [$i]["A"]));
$col_B =array(trim($allDataInSheet [$i]["B"]));
}
If 'A' has 44 variable names and 'B' has 44 values.
In this scenario,How can I assign the values of 'B' to the variable names of 'A'
Please help me to solve this
Arrays in PHP can take on two different key-types and they can mix and match. Indexed by number and indexed by string. And an array can contain any value, including an array of values. This means that you can create an array that uses the names in Array A as the keys and the values in Array B as the values for those keys.
$columns = [];
// Arrays start at 0, but since these came from excel 0 is the column header.
// You want to stop 1 entry before the count of your array. Since arrays are 0 indexed, the array count is 1 larger than the last index.
for($i=1;$i<=$arrayCount-1;$i++)
{
$a = trim($allDataInSheet [$i]["A"]);
$b = trim($allDataInSheet [$i]["B"]);
// You don't need to specify the Array constructor anymore.
// You can just use brackets to create a new array.
// Not sure if you still want these, but I left them for you.
$col_A = [$a];
$col_B = [$b];
// Assign the values of B to columns in A
if(!isset($columns[$a]) {
$columns[$a] = $b;
} else {
// Debugging message - Tried to set two values to the same name.
}
}
// Do stuff with $columns
// $columns["a"] == "b"
Above, you can see that since $allDataInSheet[$i]["A"] is the string we want, we can just use that value as our key and its matching entry in B as the value for that key.
Notice how we don't let a value get added to the array if we already have that name set. If you want $columns[$a] to be an array of values, you can change it to look like this:
if(!isset($columns[$a]){
// If we don't have an entry for $columns[$a] create an array here to hold the values for possible $b's.
$columns[$a] = [];
}
// Add $b to the $columns[$a] array.
$columns[$a][] = $b;
That will treat the $columns array as an array of arrays. Meaning that each position can hold multiple values. So, we turn it into an array and just add the $b value to that position. If we come across that $a value again, we'll see that we already have that position set and we just use the array that's already there.
Notice - we do an isset check instead of an empty check because if 'b' was actually " " or false or 0 or for some strange reason, $columns[$a] doesn't change from an empty array to an array with something in it, than we don't want to erase the value that's already there.
Good Luck!
I have the following array
$a = ["one", "dos" => "two", "three"];
As you see the second element has the key for his value set explicitely, but the other 2 items do not.
I want to loop through the array, but do something different, depending if the key for that item was set explicitly or not. Kinda like this:
foreach($a as $value){
if( has_explicit_key($value) )
// Do something
else
// Do other stuff
}
How can I achieve this?
PS: I guess I could check if the key is an integer, but if the key is set explicitly as an integer, that would not work, right?
try this
foreach($a as $key=>$value){
if( is_int($key) )
// Do something
else
// Do other stuff
}
this is the closest approach since keys are usually, 0,1,2......
In your specific case, you can exploit the fact that elements without explicit string keys automatically receive integer indexes:
$a = ["one", "dos" => "two", "three"];
foreach ($a as $k => $v) {
if (is_int($k)) {
// Do something
} else {
// Do other stuff
}
}
If you allow for the explicit keys to be scalars other than strings (integer, float, boolean, etc), then there is no way (at run-time) to distinguish between non-string keys supplied by the user and integer keys filled in by the parser. Specifically, refer to the PHP source function zend_ast_add_array_element. In that function, when the key is not explicitly given (offset IS_UNDEF), then PHP assigns one with zend_hash_next_index_insert and records no bookkeeping note of that fact.
Now, if you don't mind, and are capable of statically analyzing the data structure, just tokenize or parse the PHP code and see if T_DOUBLE_ARROW precedes the array value. This is probably not worth the effort and only works on static code.
You can loop through the array using
foreach($a as $key => $value) {
/* stuff */
}
To check if the key has been set explicitly can probably only be done by checking if the key is numerical (PHP will assign numerical keys to values without any keys in arrays).
Of course this means that you won't be able to detect a key that was set explicitly and is numeric.
So unless there's some function (which I'm unaware of) this would be the only way.
I know about function array_unshift(), but that adds to array with a autoincrement key.
For this code:
$messages[$obj_result['from']] = $obj_result;
I need to add value $obj_result in the beginning of the array. So, last added value will be in the beginning of array.
do somthing like this
$array = array("a"=>1,"b"=>2,"d"=>array("e"=>1));
$newArray["c"] = 3;
echo "<pre>";
print_r(array_merge($newArray,$array));
in array_merge first argument will be your that key value pair that you want to add in beginning.
Assuming as an array (with your desire key) you can use operator + :
$messages = obj_result + $messages;
From the manual:
while literal keys won't be touched
So you can just prepend the element, assuming the from key of the $obj_result variable is a string, all the key's will stay the same, while your new element is still on the beginning of the array.
I have an array that is associative that I have decoded from a json json_decode second value true and looks like
Array (
[test] => Array
(
[start] => 1358766000
[end] => 1358775000
[start_day] => 21
[end_day] => 21
)
)
But for some reason when I do $array[0] I get null? How can I get the array by index? Not by key name?
array_values() will give you all the values in an array with keys renumbered from 0.
The first level of the array is not numerical, it's an associative array. You need to do:
$array['test']['start']
Alternatively, to get the first element:
reset($array);
$first_key = key($array);
print_r($array[$first_key]);
You could use current.
$first = current($array); // get the first element (in your case, 'test')
var_dump($first);
This is by design . . . your JSON used a key (apparently test), which contained a JSON object. The keys are preserved when you do a json_decode. You can't access by index, though you could loop through the whole thing using a foreach.
From your comment, it sounds like you want to access previous and next elements from an associative array. I don't know a way to do this directly, but a hackish way would be as follows:
$testArr = array('a'=>'10', 'b'=>'2', 'c'=>'4');
// get numeric index of the element of interest
$keys = array_keys($testArr);
$i = array_search('b', $keys);
// get key of next element
$nextElementKey = $keys[$i+1];
// next element value
$nextElementValue = $testArry[$nextElementKey];
// get key of previous element
$prevElementKey = $keys[$i-1];
// prev value
$[prevElementValue = $testArry[$prevElementKey];
You'd probably want to add some error checking around the previous and next key calculations to handle the first and last values.
If you don't care about the data in the key, Ignacio's solution using array_keys is much more efficient.
Stumped by this one:
I have a function that returns an array of folders in a given directory. When I iterate through the array, I can see all the items. However, if I try to print the first item, I get nothing:
function get_folders($dir) {
return array_filter(scandir($dir), function ($item) use ($dir) {
return (is_dir($dir.'/'.$item) && $item != "." && $item != "..") ;
});
}
$folders = get_folders(".");
$first_folder = $folders[0];
echo $first_folder; // returns blank.
Interestingly, if I don't filter out the "." and "..", then $first_folder does print ".". Can anyone explain this?
As noted in the manual: Array keys are preserved when using array_filter().
The keys are preserved from the call to scandir() which will include the . and .. directories, meaning your filtered array will start at 2 or more (whatever the key is for the first directory).
A simple fix would be to wrap the whole thing in array_values() to get the resultant array having keys starting from 0 and incrementing by one.
return array_values(array_filter(...));
If you don't actually care about the keys, then basic array functions could be of use like key or current.
From the array_filter manual:
Iterates over each value in the input array passing them to the callback function. If the callback function returns true, the current value from input is returned into the result array. Array keys are preserved.
So, scandir($dir) gets you an array with . at key 0, thus if you later filter . out, there will be nothing at key 0 in the result.
If you want to know what the first key of the resulting array is, try the array_keys function.
EDIT: actually, salathe's suggestion to use array_values is better in your case than getting the keys from array_keys.
can you print the folders and see if there is some key you can get the first folder with as opposed to selecting the index of zero? It seems lke $folders[0] would work unless the entries are stored with a different set of indexes / keys.
Try doing a
print_r($folders)
to see if it outputs your first folder and all other folders as expected with the corresponding indexes you're looking for.
array_filter preserves array keys, so if the first two elements have been removed, then the "new first" element has an index of 2. To convert that into an array indexed starting from 0, use array_values:
return array_values(array_filter(scandir($dir), function ($item) use ($dir) {
...
As others have said, array_filter preserves the keys in the array. Given that initially the item '.' has key 0, the filtered array ends up not having any item with key 0 (you can verify this with print_r($folders). So this line:
$first_folder = $folders[0];
ends up generating an E_NOTICE saying that there is no key 0 in the array (having notices turned on would alert you to the cause of the problem immediately, I highly recommend it) and giving $first_folder the value null.
To get the first value of the filtered array, regardless of key, use reset:
$first_folder = reset($folders);
if($first_folder === false) {
echo 'No folders!';
}
else {
echo 'First folder: '.$first_folder;
}