I have seen an ampersand symbol before a variable in foreach. I know the ampersand is used for fetching the variable address which is defined earlier.
I have seen a code like this:
<?php
$arr = array(1, 2, 3, 4);
foreach ($arr as &$value) {
$value = $value * 2;
}
// $arr is now array(2, 4, 6, 8)
unset($value); // break the reference with the last element
?>
I just need to know the use of & before $value. I haven't seen any variable declared before to fetch the variable address.
Please help me why its declared like this. Any help would be appreciated.
The ampersand in the foreach-block allows the array to be directly manipulated, since it fetches each value by reference.
$arr = array(1,2,3,4);
foreach($arr as $value) {
$value *= 2;
}
Each value is multiplied by two in this case, then immediately discarded.
$arr = array(1,2,3,4);
foreach($arr as &$value) {
$value *= 2;
}
Since this is passed in by reference, each value in the array is actually altered (and thus, $arr becomes array(2,4,6,8))
The ampersand is not unique to PHP and is in fact used in other languages (such as C++). It indicates that you are passing a variable by reference. Just Google "php pass by reference", and everything you need to explain this to you will be there. Some useful links:
http://www.php.net/manual/en/language.references.pass.php
Are PHP Variables passed by value or by reference?
http://www.learncpp.com/cpp-tutorial/73-passing-arguments-by-reference/ (this is for C++, but the same principle applies in PHP)
Related
I'm trying to find a simpler way to create new arrays from existing arrays and values. There are two routines I'd like to optimize that are similar in construction. The form of the first one is:
$i = 0;
$new_array = array();
foreach ($my_array as $value) {
$new_array[$i][0] = $constant; // defined previously and unchanging
$new_array[$i][1] = $value; // different for each index of $my_array
$i++;
}
The form of the second one has not one but two different values per constant; notice that $value comes before $key in the indexing:
$i = 0;
$new_array = array();
foreach ($my_array as $key => $value) {
$new_array[$i][0] = $constant; // defined previously and unchanging
$new_array[$i][1] = $value; // different for each index of $my_array
$new_array[$i][2] = $key; // different for each index of $my_array
$i++;
}
Is there a way to optimize these procedures with shorter and more efficient routines using the array operators of PHP? (There are many, of course, and I can't find one that seems to fit the bill.)
I believe a combination of Wouter Thielen's suggestions regarding the other solutions actually holds the best answer for me.
For the first case I provided:
$new_array = array();
// $my_array is numeric, so $key will be index count:
foreach ($my_array as $key => $value) {
$new_array[$key] = array($constant, $value);
};
For the second case I provided:
// $my_array is associative, so $key will initially be a text index (or similar):
$new_array = array();
foreach ($my_array as $key => $value) {
$new_array[$key] = array($constant, $value, $key);
};
// This converts the indexes to consecutive integers starting with 0:
$new_array = array_values($new_array);
it is shorter, when you use the array-key instead of the $i-counter
$new_array = array();
foreach ($my_array as $key => $value) {
$new_array[$key][0] = $constant; // defined previously and unchanging
$new_array[$key][1] = $value; // different for each index of $my_array
}
Use array_map:
$new_array = array_map(function($v) use ($constant) {
return array($constant, $v);
}, $my_array);
If you want to use the keys too, for your second case:
$new_array = array_map(function($k, $v) use ($constant) {
return array($constant, $v, $k);
}, array_keys($my_array), $my_array);
Assuming the $constant variable is defined in the caller's scope, you'll need to use use ($constant) to pass it into the function's scope.
array_walk is similar, but modifies the array you pass to it, so if you want to update $my_array itself, use array_walk. Your second case then becomes this:
array_walk($my_array, function(&$val, $key) use($constant) {
$val = array($constant, $val, $key);
});
In both examples above for the second case, you'll end up with an associative array (i.e. with the keys still being the keys for the array). If you want to convert this into a numerically indexed array, use array_values:
$numerically_indexed = array_values($associative);
I asked a question similar to this a few days ago, check it out:
PHP - Fastest way to convert a 2d array into a 3d array that is grouped by a specific value
I think that you have an optimal way when it comes to dealing with large amount of data. For smaller amounts there is a better way as was suggested by the benchmarks in my question.
I think too that readability and understanding the code can also be an issue here and I find that things that you can understand are worth more later on than ideas that you do not really grasp as it generally takes a long time to understand them again as it can be quite confusing while debugging issues.
I would suggest, you take a look at the differences between JSON encoded arrays and serialised arrays as there can be major performance differences when working with the two. It seems that as it is now JSON encoded arrays are a more optimised format (faster) for holding and working with data however this will likely change with PHP 7. It would be useful to note that they are also more portable.
Further Reading:
Preferred method to store PHP arrays (json_encode vs serialize)
http://techblog.procurios.nl/k/n618/news/view/34972/14863/cache-a-large-array-json-serialize-or-var_export.html
base on my understanding, this how list() work.
list($A1,$A2,$A3) = array($B1,B2,B3);
So with the help of list() we can assign value out from array accordingly.
here is my question... how to generate a dynamic list()?
1). base on database return result, I'm not sure how many of it but I assign it all into array
2). so we can use count(array) to know how many of it.
3). so then HOW CAN I GENERATE/PREPARE a list for it?
Example: client A, have 3 kids, name Apple, Boy, Cat
so I use list($kid1, $kid2, $kid3) for it.
but when client B, have more then 3 kids, I only get first 3
or if client C, have only 1 kids, then error encounter.
I know if base on the situation above, there is many way to solve it without using list()
but I wish to know or find out the solution with using list().
How to generate dynamic list() base on count of array()
thanks guys/gals
If you have a variable number of elements, use arrays for them! It does not make sense to extract them into individual variables if you do not know how many variables you'll be dealing with. Say you did extract those values into variables $kid1 through $kidN, what is the code following this going to do? You have no idea how many variables there are in the scope now, and you have no practical method of finding out or iterating them next to testing whether $kid1 through $kidN are isset or not. That's insane use of variables. Just use arrays.
Having said that, variable variables:
$i = 1;
foreach ($array as $value) {
$varname = 'kid' . $i++;
$$varname = $value;
}
You can create a lambda expression with create_function() for this. The list() will be only accessible within the expression.
This creates variables $A1, $A2, .... $AN for each element in your array:
$list = array("a", "b", "c", "d");
extract(array_combine(array_map(function($i) {
return "A" . $i;
}, range(1, count($list))), $list));
echo implode(" ", array($A1, $A2, $A3, $A4)), PHP_EOL;
You can modify the name of the variables in the array_map callback. I hope I'll never see code like that in production ;)
This is not what PHP's list is meant for. From the official PHP docs
list is not really a function, but a language construct.
list() is used to assign a list of variables in one operation.
In other words, the compiler does not actually invoke a function but directly compiles your code into allocations for variables and assignment.
You can specifically skip to a given element, by setting commas as follows:
list($var1, , $var2) = Array($B1, B2, B3);
echo "$var1 is before $var2 \n";
or take the third element
list( , , $var3) = Array($B1, B2, B3);
(I am assuming B2, B3 are constants? Or are you missing a $?)
Specifically using list, you can use PHP's variable variables to create variables from an arbitrary one-dimensional array as follows:
$arr = array("arrindex0" => "apple", "banana", "pear");
reset($arr);
while (list($key, $val) = each($arr)) {
$key = is_numeric($key) ? "someprefix_" . $key : $key;
echo "key sdf: $key <br />\n";
$$key = $val;
}
var_dump($arrindex0, $someprefix_0, $someprefix_1);
Result
string 'apple' (length=5)
string 'banana' (length=6)
string 'pear' (length=4)
$index = 0;
foreach ($sxml->entry as $entry) {
$array + variable index number here = array('title' => $title);
$index++;
}
I'm trying to change an array name depending on my index count. Is it possible to change variable name (ie. $array1, $array2 $array3 etc.) in the loop?
Edit:
After the loop has finished, I will generate a number number (depending on the count of $index) and then use this array... probably it's a stupid way of accomplishing what Im trying to do, but I don't have a better idea.
You might want to try this instead:
$index = 0;
$arrays = array();
foreach ($sxml->entry as $entry) {
$arrays[$index] = array('title' => $title);
$index++;
}
While it is technically possible to do what you are asking, using an array of arrays will probably work better from you.
This type of indexing is exactly what arrays are designed for, you have a lot of items and want to be able to refer to them by number.
Unless you have a very specific reason to use the name of the variable to represent it's number you will probably have a much simpler time using it's index in the outer array.
Yes you can user an associate array. Generating a string dynamically based on the iteration number and using that as a key in the array.
You can use variable variables. php.net
PHP supports Variable variables:
$num = 1;
$array_name = 'array' . $num;
$$array_name = array(1,2,3);
print_r($array1);
http://php.net/manual/en/language.variables.variable.php
What is the difference in the following array notations: $arr[$key] = $value and $arr[] = $value, which is a better way ?
function test(){
$key = 0;
$a = array(1,2,3,4,5);
foreach($a as $value){
$a[$key] = $value;
$key++;
}
print_r($a);
}
versus
function test(){
$a = array(1,2,3,4,5);
foreach($a as $value){
$a[] = $value;
}
print_r($a);
}
They are different.
$a[] = 'foo';
Adds an element to the end of the array, creating a new key for it (and increasing the overall size of the array). This is the same as array_push($array, 'foo');
$key = 0;
$a[$key] = 'foo';
Sets the 0 element of the array to foo, it overwrites the value in that location... The overall size of the array stays the same... This is the same as $array = array_slice($array, 0, 1, 'foo'); (but don't use that syntax)...
In your specific case, they are doing 2 different things. The first test function will result in an array array(1,2,3,4,5), whereas the second one will result in array(1,2,3,4,5,1,2,3,4,5). [] always adds new elemements to the end.... [$key] always sets....
$arr[$key] = $value sets a specific key to a specific value.
$arr[] = $value adds a value on to the end of the array.
Neither is "better". They serve completely different roles. This is like comparing writing and drawing. You use a pen for both of them, but which you use depends on the circumstance.
One ($a[$key] = $value) youare specifying the $key where PHP will override that array entry if you use the same key twice.
The other ($a[] = $value) PHP is handling the keys itself and just adding the array entry using the next available key.
The whole thing that you are doing is a bit redundant though, as in the first example you are trying to loop through the array setting its values to itself. In the second example you are duplicating the array.
If you want to append an element to the array I would use
$arr[] = $value;
It is simpler and you get all the information on that line and don't have to know what $key is.
I've created this method to change every value in an array. I'm kinda new to PHP, so I think there should be a more efficient way to do this.
Here's my code:
foreach($my_array as $key => $value)
{
$my_array[$key] = htmlentities($value);
}
Is there a better way to do this?
Thank you in advance.
You'd probably be better off with array_map
$my_array = array_map( 'htmlentities' , $my_array);
You can reference the array and change it
foreach ($array as &$value) {
$value = $value * 2;
}
When you need to apply a function to the value and reassign it to the value, Galen's answer is a good solution. You could also use array_walk(), although it doesn't read as easily as a nice, simple loop.
When you only need to assign, for example, a primitive value to each element in the array, the following will work.
If your keys are numeric, you can use array_fill():
array_fill(0, sizeof($my_array), "test");
If you're using an associative array, you can probably use array_fill_keys(), with something like:
array_fill_keys(array_keys($my_array), "test");
If you mark $value as a reference (&$value) any change you make on $value will effect the corresponding element in $my_array.
foreach($my_array as $key => &$value)
{
$value = "test";
}
e.g.
$my_array = array(1,2,3,4,5,6);
foreach($my_array as &$value)
{
$value *= 5;
}
echo join($my_array, ', ');
prints
5, 10, 15, 20, 25, 30
(And there's also array_map() if you want to keep the original array.)
foreach($my_array as &$value)
{
$value = "test";
}
You could use array_fill, starting at 0 and going to length count($my_array). Not sure if it's better though.
Edit: Rob Hruska's array_fill_keys code is probably better depending on what you define as better (speed, standards, readability etc).
Edit2: Since you've now edited your question, these options are now no longer appropriate as you require the original value to be modified, not changed entirely.