I have a loop like this below:
foreach ($header as $i) {
$i += $i;
}
I am trying to load a variable ($i) and then outside of that loop echo that variable like this below:
echo $i;
However it always returns 0;
Is it possible to get it to return the value that it created in the loop?
You can use implode() to combine all the values.
$all = implode('', $header);
http://php.net/implode
$i is re-assigned every time the loop iterates.
create a variable outside the loop, add to it during the loop, and echo again outside of it.
$outside_var = 0;
foreach ($header as $i) {
$outside_var += $i;
}
echo $outside_var;
foreach ($header as $i) {
$i += $i;
}
The above code has many problems. Other answers solve them, but with bare explanations, so you might find this helpful. For the purposes of this answer, I will assume $header contains array('a', 'b', 'c'), and that your intention was to concatenate the values.
Firstly, you're using the numeric addition operator += instead of the string concatenation operation .=. This is why $i is always 0: The values of $header are converted to integers each time you attempt to add with +=, assuming they don't start with numbers, they will always convert to the integer 0.
Secondly, if you were concatenating with .=, you'd be assigning to $i each time through the loop, so its previous value would be destroyed. On the first pass of the loop, you're effectively doing this:
$i = 'a';
$i .= $i' // aa
On the second pass, you're doing this:
$i = 'b';
$i .= $i; // bb
And so on. You need to use a different variable to store each element of the array and hold the concatenated values. Otherwise, when the loop exists, $i will always be the last value of the array, duplicated.
Finally, you should always declare your variables before attempting to read from them, which is implied by all the shorthand (+=,.=,*=,etc) operators. It's a very good idea to include E_NOTICE in error_reporting in php.ini so that you'll see the notice this raises.
Related
Hey everyone I have a question about arrays and loops in PHP.
For a game I'm making, I need to write a function that generates a stack of crystal_id's based on a given size and ratio.
The ratio is the ratio between black crystals and different colored crystal (so a ratio of 0,25 (1:4) and a stack of 50 would yield a stack with 40 black crystals and 10 colored crystals).
I have all the math to calculate the amount of crystals per color and stuff figured out, but I can't figure out how to create an array with the right amount of colored crystals where each color is represented equally.
For reference, the array the code gets to choose from is a variable called $crystals_array, which is an array filled with integers where each integer represents a different colored crystal (e.g. [2,3,4,5,6]).
In the above case we have 5 different colored crystals and we needed a total of 10 colored crystals where each crystal is represented equally. So I need to create an array that looks a little something like this:
[2,2,3,3,4,4,5,5,6,6].
The code I have so far is this:
for($i = 0; $i <= count($amount_crystals_color) - 1; $i++)
{
$array = array_fill(0, $amount_crystals_per_color_stack, $crystals_array[$i]);
$i++;
}
Using the above example $amount_crystals_per_color_stack is equal to 2 and amount_crystals_color is equal to 5.
When executing this code it outputs an array: [2,2] which is how many 2's we need, but I can't figure out how to add the remaining crystals to this array.
Can anyone help me out?
Your code has several problems and i will address each of them individually.
Using the for loop to iterate over an array
You are using a for loop in your code, that has the following loop head:
for($i = 0; $i <= count($crystals_array) - 1; $i++)
The loop had consists of three parts, each separated by a semicolon (;).
The first part $i = 0 is the initialization part. Here you initialize a variable, that is later used as an iterator, which shall change in each loop iteration. You could name this the start point as well.
The second part $i <= count($crystals_array) - 1 is the condition part. A condition is formed, that shall express for how long the loop shall iterate. As long as the expression evaluates as true, the loop will run again. Therefore this condition is evaluated at the start of each iteration. As soon as the condition evaluates as false the loop will end. Therefore this part can be named endpoint as well.
The third part $i++ is the step size. This is executed at the end of each iteration and determines how the iterator (the variable you defined in the first part) shall change. $i++ is in this context equal to $i = $i + 1 and represents a step size of 1. Therefore the variable $i gets increased by 1 for each run of the loop.
This said, you can improve and fix your code regarding the for loop with two changes:
Save functions, that are executed in your condition part into an variable, if they return a constant result for each iteration. You use the count() function, which will then count your array again for each iteration of the for loop. By saving it in a variable $count = count($crystals_array); before the for loop and changing the condition to $i < $count, the function is only called once and your code gets faster.
Do not change the iterator variable $i outside of your loop header. This is really bad code style. You added the line $i++; to the end of your loop, but that is already done in the step size part of the for header. Because that is executed at the and of each iteration as well you increased the step size to two, meaning that you only run the for loop with $i = 0, $i = 2 and $i = 4 instead of for each element.
For your code the usage of the $i iterator is only to address the elements of the initial array. Even though you should understand the for loop for the future, you should use a foreach loop for this case instead. The following code would be equivalent to your for loop.
//This code still contains another major bug and is jsut a partial improvvement
foreach($crystals_array as $crystal) {
$array = array_fill(0, $amount_crystals_per_color_stack, $crystal);
}
As you can see, you neither need to worry about counting the initial array, nor in which index the current value is. Instead the variable $crystal will automatically contain the next element for each iteration.
Appending elements to an array
You used the following line to save the newly generated elements in your array:
$array = array_fill(0, $amount_crystals_per_color_stack, $crystal);
If you look closely, you use a standard assignment with $array = at the beginning of your line. This means, that (like with each variable assignment) the previous value of the variable gets overwritten by the new value provided from the right side of the assignment. What you do not want yet is to overwrite the array, but to append something to it.
This can be done by adding two squared brackets to the end of the variable name: $array[] = .... Now, if the variable $array is really an array, what ever value is on the right side of the assignment will be appended to the array, instead of overwriting it.
Managing result types the right way
The following line still contains a major problem:
$array[] = array_fill(0, $amount_crystals_per_color_stack, $crystal);
The result type of array_fill() is an array itself. By appending it to the previous array, you would get the following structure:
$array = [
[2, 2],
[3, 3],
[4, 4],
[5, 5],
[6, 6],
];
As you can see, the code did exactly what it should but not what you wanted. Each result (array) was appended to the array. The result is therefore an array or arrays (or a multidimensional array). What you want instead, is that the values of the result are appended to the existing array.
PHP offers a function for that, named array_merge(). This function takes all elements for one (or more) array(s) and appends them to the end of the first array, that was given to the function. You can use it as followed:
$newCrystals = array_fill(0, $amount_crystals_per_color_stack, $crystal);
$array = array_merge($array, $newCrystals);
As you can see the latter line contains a normal assignment again. ($array =) This is because array_merge() does not modify the first array given to it, but creates a new array with the merged fields. Therefore the new array contains all values from the old one and it is safe to overwrite the old one with it.
The complete code would therefore be:
$array = [];
foreach($crystals_array as $crystal) {
$newCrystals = array_fill(0, $amount_crystals_per_color_stack, $crystal);
$array = array_merge($array, $newCrystals);
}
As I understood the problem
$crystals_array = [2,3,4,5,6];
$amount_crystals_per_color_stack = 2;
$res = [];
foreach($crystals_array as $v) {
// repeat each item from array $amount_crystals_per_color_stack times
$res = array_merge($res, array_fill(0, $amount_crystals_per_color_stack, $v));
}
print_r($res); // [2,2,3,3,4,4,5,5,6,6]
You need to merge your array at each iteration of the loop (repl online) or you lose the result each time.
Like:
$array = array();
for($i = 0; $i < count($amount_crystals_color); $i++)
{
$array = array_merge($array, array_fill(0, $amount_crystals_per_color_stack, $crystals_array[$i]);
}
Also you don't need the $i++ in the loop, because it iterate twice otherwise, and you don't need count(..)-1 if the condition is < instead of <=.
You could use simple foreach() to achieve this-
$amount_crystals_per_color_stack = 2;
$array = [2,3,4,5,6];
$result = array();
foreach($array as $a){
for($i=1;$i<=$amount_crystals_per_color_stack;$i++){
array_push($result, $a);
}
}
print_r($result);
I have a foreach loop like below code :
foreach($coupons as $k=>$c ){
//...
}
now, I would like to fetch two values in every loop .
for example :
first loop: 0,1
second loop: 2,3
third loop: 4,5
how can I do ?
Split array into chunks of size 2:
$chunks = array_chunk($coupons, 2);
foreach ($chunks as $chunk) {
if (2 == sizeof($chunk)) {
echo $chunk[0] . ',' . $chunk[1];
} else {
// if last chunk contains one element
echo $chunk[0];
}
}
If you want to preserve keys - use third parameter as true:
$chunks = array_chunk($coupons, 2, true);
print_r($chunks);
Why you don't use for loop like this :
$length = count($collection);
for($i = 0; $i < $length ; i+=2)
{
// Do something
}
First, I'm making the assumption you are not using PHP 7.
It is possible to do this however, it is highly, highly discouraged and will likely result in unexpected behavior within the loop. Writing a standard for-loop as suggested by #Rizier123 would be better.
Assuming you really want to do this, here's how:
Within any loop, PHP keeps an internal pointer to the iterable. You can change this pointer.
foreach($coupons as $k=>$c ){
// $k represents the current element
next($coupons); // move the internal array pointer by 1 space
$nextK = current($coupons);
prev($coupons);
}
For more details, look at the docs for the internal array pointer.
Again, as per the docs for foreach (emphasis mine):
Note: In PHP 5, when foreach first starts executing, the internal array pointer is automatically reset to the first element of the
array. This means that you do not need to call reset() before a
foreach loop. As foreach relies on the internal array pointer in PHP
5, changing it within the loop may lead to unexpected behavior. In PHP
7, foreach does not use the internal array pointer.
Let's assume your array is something like $a below:
$a = [
"a"=>1,
"b"=>2,
"c"=>3,
"d"=>4,
"e"=>5,
"f"=>6,
"g"=>7,
"h"=>8,
"i"=>9
];
$b = array_chunk($a,2,true);
foreach ($b as $key=>$value) {
echo implode(',',$value) . '<br>';
}
First we split array into chunks (the parameter true preserves the keys) and then we do a foreach loop. Thanks to the use of implode(), you do not need a conditional statement.
well this'd be 1 way of doing it:
$keys=array_keys($coupons);
for($i=0;$i<count($keys);++$i){
$current=$coupons[$keys[$i]];
$next=(isset($keys[$i+1])?$coupons[$keys[$i+1]]:NULL);
}
now the current value is in $current and the next value is in $next and the current key is in $keys[$i] and the next key is in $keys[$i+1] , and so on.
I know there are a lot of similar questions on here, and I think I've read them all. My problem is that I am attempting to loop through a list of arrays and grab one value from each. The arrays have been set up by a third party, and I don't have the access to configure how I am receiving them. Here's what I have so far:
for ($i = 0; $i < $length; $i++) {
// Both of these work and return the value I need
echo $post->related_credits_0_related_show[0];
echo "{$post->related_credits_0_related_show[0]}"
// But none of these do, and I need to loop through a handful of arrays
echo "{$post->related_credits_{$i}_related_show[0]}";
echo "{$post->related_credits_${i}_related_show[0]}";
echo "{$post->related_credits_{${i}}_related_show[0]}";
echo "{$post->related_credits_".$i."_related_show[0]}";
}
I've tried many (many!) more combinations that I won't include. I've also tried converting $i to a string. Been knocking my head against this for awhile.
Thanks ahead of time for any help.
You need to use variable variables here. The basic usage is as follows:
$var = 'Hello there!';
$foo = 'var';
echo $$foo;
^^--- note the double $-sign
This will output:
Hello there!
Instead of $$foo, you can also write the following:
echo ${"$foo"};
If the variable name is more complex, you can can also do:
echo ${"some_stuff_{$foo}_more_stuff"};
In this case, the string that denotes the variable name contains a variable, and that variable is also wrapped inside curly braces ({}). This is done in order to avoid problems with constants, array indexes etc. But if your use-case doesn't involve any of those, you don't have to worry about it.
For your specific problem, you can use the following:
for ($i=0; $i < $length; $i++) {
$post->{"related_credits_{$i}_related_show"}[0];
}
Or, if you prefer concatenation:
for ($i=0; $i < $length; $i++) {
$res = $post->{'related_credits_'.$i.'_related_show'}[0];
}
See the documentation on Variable Variables for more information.
You can use this:
$varname = "related_credits_$i_related_show";
$array = $post->$varname;
echo $array[0];
A shorter form would be:
$post->{"related_credits_{$i}_related_show"}[0];
Here you find all about so called "variable variables" : http://www.php.net/manual/en/language.variables.variable.php
hello all this is my code i am having problem in achiving this
for($a=1;$a++,$a<25;){
echo $a.',';
}
this gives something like 1,2,3,4,5,6,7,8.......
but i dont want to print it i just want to store it into a variable say b and print it after the loop is over..
like
for($a=1;$a++,$a<25;){
$b=$a.',';
}
echo $b;
can anyone just give me an idea how to do this ??
the variable should have the same value like 1,2,3,4,5,6,7,8,9.............
In the C++ language, you could use a vector:
std::vector<int> a;
int i = 0;
for (i = 0; i < limit; i++)
{
a.push_back[i];
}
// Access them outside the for loop:
std::cout << "a[5]: " << a[5] << "\n";
Use an array, and then implode the resulting filled array.
$array = array();
for($a=1;$a<25;$a++){
array_push($array, $a);
}
echo implode(',', $array);
What you want is $b .= $a.",";
That will append each variable to $b. But you will also need to remove the last ',' either through a substring or a if statement inside the loop
You need an array variable here. Store the values in an array and then run afor loop to print all the values.
In php this is how you should do:
for($a=1;$a++,$a<25;){
$b .= $a.',';
}
echo $b;
Also, I think your for is wrong. The normal form of a for should be for(initialization ; conditions ; operations).
With your for you will achieve something like 2,3,4....
im trying to create an array from a loop in PHP.
I want the array to end up something like $array(100,100,100,100), this is my code:
$x = 0;
while($x < 5){
$array[$x] = 100;
$x++;
}
echo $array[0];
It outputs 1 instead of 100.
Can someone tell me where i'm going wrong.
Even though it works perfectly for me, you should be initialising the variable beforehand.
$array = array();
For example, if $array is non-empty string, you will see the output of 1.
You can just use the predefined array_fill function for that:
$array = array_fill(0, 5, 100);
The other answers pretty much cover this. I would, however, recommend you use a for loop for this instead of a while loop if you're going to use a loop rather than a function to do it.
$array = array();
for($x=0; $x<5; $x++) {
$array[$x] = 100;
}
In fact, you could make this even shorter.
$array = array();
for($x=0; $x<5; $array[$x++]=100);
It's perfectly valid to have a for loop statement instead of a block. And blocks can go anywhere too; they don't need an if statement, for loop, while loop, or whatever, before them.