I have this code block
<?php
$myArray = array('a', 'b', 'c');
foreach ($myArray as $k => $v) {
echo $v;
for ($i = 1; $i < 5; $i++) {
if ($i == $k) {
break;
}
echo $i; //a1234bc1
}
}
?>
and I have no problem with it until I get to the value after c. Shouldn't be 1234 instead of 1 ? am I missing something?
Because,
In the first iteration in foreach value of $k is 0 and there is no 0 in for loop, it covers all and print all 1 to 4, so output is a1234
In the second iteration in foreach value of $k is 1 and for loop start from 1,so in if condition it is in first iteration, so loop stop in first iteration of for loop and print only b , so output is a1234b
similarly in third iteration in foreach value of $k is 2 and for loop start from 1,so in if condition it is in second iteration, so loop stop in second iteration of for loop after print c1 , so output is a1234bc1
I think now its clear to you.
You foreach ($myArray as $k => $v) loop is executed 3 times as $myArray has 3 Elements.
First run
$k = 0 which is the index of the first element, $v = "a"
echo $v; // Outputs a
Output of your loop
for ($i = 1; $i < 5; $i++) { ... }
Outputs all numbers from 1 to 5 and stops once the exact value of $k is met. $k is 0 so the condition (break) never gets triggered. Hence all numbers from 1 to 5 are echoed.
Output so far:
a1234
Second run
$k = 1 which is the index of the second element, $v = "b"
for ($i = 1; $i < 5; $i++) { ... }
Output of your loop
for ($i = 1; $i < 5; $i++)
Outputs all numbers from 1 to 5 and stops once the exact value of $k is met. As $k is 1 the break gets executed on first run of llop, hence no output.
Output so far:
a1234b
Third run
$k = 2 which is the index of the third element, $v = "c"
echo $v; // Outputs c
Output of your loop
for ($i = 1; $i < 5; $i++) { ... }
Outputs all numbers from 1 to 5 and stops once the exact value of $k is met. As $k euqals 2 this time the loop gets executed once outputting 1. On second run the break executes and terminates oputput
Final output:
a1234bc1
1st Iteration:
1st loop
$k = 0; $v = a;
2nd loop
$i doesn't equal $k;
Output: a1234
2nd Iteration:
1st loop
$k = 1; $v = b;
2nd loop
$i equals $k(i.e 1);
Output: a1234b
3nd Iteration:
1st loop
$k = 2; $v = c;
2nd loop
$i equals $k(i.e 2);
Output: a1234bc1
Try this
$myArray = array('a', 'b', 'c');
foreach ($myArray as $k => $v) {
echo $v;
for ($i = 1; $i < 5; $i++) {
echo $i; //a1234b1234c1234
}
}
Remove if condition .
Related
I have an associative array that might contain duplicates. I am trying to loop through the array and compare the current element with the next element in the array. If there is a duplicate, it should be removed.
The code below removes one instance of the element. In the test array I'm using, I have 3 duplicate part numbers, but my code only removes one. I'm left with two. I only want one to remain.
$length = count($items);
for($i = 0; $i < $length -1; $i++){
if($items[$i]['part_number'] == $items[$i+1]['part_number']){
unset($items[$i+1]);
$items = array_values($items);
}
}
What am I doing wrong here?
You need to loop backwards through the array, and delete the current item.
$length = count($items);
for($i = $length - 1; $i > 0; $i--){
if($items[$i]['part_number'] == $items[$i-1]['part_number']){
unset($items[$i]);
}
}
becuase your code is
The $ items value is in the for statement.
if you want unique array, you have to array_unique function
http://php.net/manual/en/function.array-unique.php
In your case after you unset element, $i++ in for loop, you reindexed your array and you skip one element. Add $i-- if you unset item. Or you can reindex your array after for loop.
This is also a very simple example you can start improving with.
<?php
$test = ['sample', 'sample', 'sample', 'not', 'not', 'no', 'no'];
$test2 = [];
$k = 0;
foreach ($test as $key => $value) {
if ($key == 0) {
$test2[$k] = $value;
$k++;
} else {
if ($test2[$k - 1] != $value) {
$test2[$k] = $value;
$k++;
}
}
}
$test = $test2;
var_dump($test);
One dirty hack is to check again if you have a duplicate by decreasing $i.
for($i = 0; $i < $length -1; $i++){
if($items[$i]['part_number'] == $items[$i+1]['part_number']){
unset($items[$i+1]);
$items = array_values($items);
$i--;
}
}
This way it will again test your previous value against next item in array.
So if 0==1, then next time if 0==2.
Your code did 0==1 then (2)==(3).
I've had this problem a few times now when for looping over an array item.
In this instance I'm generating all 2 letter combinations of the alphabet.
The code works (and I know there's a much easier way of doing it with 2 for loops, but I'm trying something different).
However I have to do count -1 as count() returns the number 26 for the array length, however the 26th item obviously doesn't exist as it's 0 based?
Is there not a version of count() that works on a zero-based basis?
<?php
$alphas = range('a', 'z');
$alphacount = count($alphas);
// Why do I have to do this bit here?
$alphaminus = $alphacount -1;
$a = 0;
for ($i=0;$i<$alphacount;$i++) {
$first = $alphas[$a];
$second = $alphas[$i];
if ($i === $alphaminus && $a < $alphaminus ) {
$i = 0;
$a ++;
}
echo "$first$second<br>";
}
?>
Without $alphaminus = $alphacount -1; I get undefined offset 26?
How about:
<?php
$alphas = range('a', 'z');
$alphacount = count($alphas);
$a = 0;
for ($i=0;$i<$alphacount;$i++) {
$first = $alphas[$a];
$second = $alphas[$i];
if ($i >= $alphacount && $a < $alphaminus ) {
$i = 0;
$a ++;
}
echo "$first$second<br>";
}
So you don't have to to -1 since you don't like it! :)
And how about:
$alphas = range('a', 'z');
for ($i = 0; $i < count($alphas); $i++) {
for ($a = 0; $a < count($alphas); $a++) {
echo "{$alphas[$i]}{$alphas[$a]}\n";
}
}
Or forget about arrays! This is more fun :)
array_walk($alphas, function ($a) use ($alphas) {
array_walk($alphas, function ($b) use ($a) {
print "$a$b\n";
});
});
The problem is that you reset $i to 0 in the loop; then on encountering the end of the loop $i is incremented, so the next run in the loop will be with $i = 1 instead of $i = 0.
That is, the next subrange of letters starts with (letter)b instead of (letter)a. (See your output: the next line after az is bb rather than ba.)
Solution: reset $i to -1 in the loop, then at the end it will run with the value 0 again.
You have 26 characters, but arrays in PHP are indexed from 0. So, indexes are 0, 1, ... 25.
count is 1-based and arrays created by range() are 0-based.
It means that:
$alphas[0] == a
$alphas[25] == z
$count($alphas) = 26; // there are 26 elements. First element is $alphas[0]
Why does it have to be so complicated? You could simply do
foreach ($alphas as $alpha)
{
foreach($alphas as $alpha2)
{
echo $alpha.$alpha2."<br>";
}
}
Note: It is mostly not a good idea to manipulate the loop counter variable inside the body of that very loop. You set $i to 0 on a certain condition. That could give you unexpected results, hence the reason why you have to navigate around it.
Well I'm stuck with this one.
I have a foreach loop nested in another foreach loop. Now on certain conditions I need to run the outer loop once again with the same key.
While there is this function prev($array), which would set the iterator to the previous position, this does not seem to work and the php docs says
As foreach relies on the >internal array pointer, changing it within the loop may lead to unexpected behavior.
The array I am working on is an associative array, so obviously I cannot easily switch to integer indexed iterations.
$arrLocalCopy = $this->arrPrintOut;
$groupCounter = 0;
foreach($this->arrPrintOut as $kOne => $rowA){
//first and last row contain titles and totals, so we skip them
if($groupCounter < 1 || $groupCounter == sizeof($this->arrPrintOut)-1 ){ $groupCounter++; continue; }
$rowCounter = 0;
foreach($arrLocalCopy as $k => $rowB){
//skip rows that are "before" the outer loops row, as we want to compare only rows below the row we compare to.
if ($rowCounter <= $groupCounter || $rowCounter == sizeof($arrLocalCopy)-1 ) { $rowCounter++; continue; }
//If those values are the same, then values belong to the same group and must be summed together.
if($rowA['t']==$rowB['t'] && $rowA['y']==$rowB['y'] && $rowA['g']==$rowB['g'] && $rowA['q']==$rowB['q'])
{
//if values are the same, then data belongs to one group, lets group them together.
$this->arrPrintOut[$kOne]['s'] += $rowB['s'];
$this->arrPrintOut[$kOne]['b'] += $rowB['b'];
$this->arrPrintOut[$kOne]['v'] += $rowB['v'];
$this->arrPrintOut[$kOne]['r'] += $rowB['r'];
$this->arrPrintOut[$kOne]['k'] += $rowB['k'];
$this->arrPrintOut[$kOne]['n'] += $rowB['n'];
$this->arrPrintOut[$kOne]['m'] += $rowB['m'];
$this->arrPrintOut[$kOne]['l'] += $rowB['l'];
unset($this->arrPrintOut[$k]); //row has been grouped to the current row, so we remove it from the array and from the copy.
unset($arrLocalCopy[$k]);
prev($this->arrPrintOut); //we need to run the outer loop with the same key again, as probably there is another row which could be grouped together with this row.
$groupCounter--;
}
$rowCounter++;
}
$groupCounter++;
}
Here is a code sample.
$rollback is a variable to check if we prev() already
$max is the number of iterations. If you prev() you have to increment it.
<?php
$array = array(1 => "a", 6 => "b", 19 => "c");
$rollback=0;
$max = sizeof($array);
for ($i=0; $i<$max; $i++) {
$key = key($array);
$value = $array[$key];
print "$key => $value\n";
next($array);
if ($value == "b" && $rollback == 0) {
prev($array);
$rollback = 1;
$max++;
}
}
I need to be able to loop an array of items and give them a value from another array and I cant quite get my head around it.
My Array
$myarray = array('a','b','c');
Lets say I have a foreach loop and I loop through 6 items in total.
How do I get the following output
item1 = a
item2 = b
item3 = c
item4 = a
item5 = b
item6 = c
My code looks something like this.
$myarray = array('a','b','c');
$items = array(0,1,2,3,4,5,6);
foreach ($items as $item) {
echo $myarray[$item];
}
Online example.
http://codepad.viper-7.com/V6P238
I want to of course be able to loop through an infinite amount of times
$myarray = array('a','b','c');
$count = count($myarray);
foreach ($array as $index => $value) {
echo $value . ' = ' . $myarray[$index % $count] . "\n";
}
% is the modulo-operator. It returns
Remainder of $a divided by $b.
what means
0 % 3 = 0
1 % 3 = 1
2 % 3 = 2
3 % 3 = 0
4 % 3 = 1
and so on. In our case this reflects the indices of the array $myarray, that we want to retrieve.
If you want an arbitrary number of loops to be done, you can use the modulus operator to cycle through your keys:
$loop = //how much you want the loop to go
//...
for ($i = 0, $i < $loop, $i++) {
$key = $i % count($myarray);
echo $i, ' = ', $myarray[$key];
}
I think what you are looking for is the modulo operator. Try something like this:
for ($i = 1; $i <= $NUMBER_OF_ITEMS; $i++) {
echo "item$i = ".$myarray[$i % count($myarray)]."\n";
}
am working on php loops and i find myself that i need to write a nested loop bur when i try to combine foreach and for loop it yield to unexpected result
Here are my codes
foreach ($district_ward as $key => $value) {
$ward_ids = array_keys($district_ward[$key]);
echo $key;
for ($x = 0; $x < count($ward_ids)-1; $x++) {
$district_village[$key]= array_merge($value[$ward_ids[$x]], $value[$ward_ids[$x+1]]);
}
}
This gives me this
347
but when i print the value of $key within the for loop, that is
foreach ($district_ward as $key => $value) {
$ward_ids = array_keys($district_ward[$key]);
for ($x = 0; $x < count($ward_ids)-1; $x++) {
echo $key;
$district_village[$key]= array_merge($value[$ward_ids[$x]], $value[$ward_ids[$x+1]]);
}
}
i get this
3
I'm just going to guess that your 2nd and 3rd array are only one entry long. The condition for the loop specifies $x < count($ward_ids) - 1. If your array only has one entry, one - 1 will make it loop 0 times. In other words, your inner loop is not executed at all.
Are you printing this to a html page? Are your keys 3, 4 and 7? They would appear as 347 if you were echoing to an html page. Try
echo "$key<br />\n";
or even
echo "<pre>".print_r($district_ward)."</pre>";
before the loop to see what the array looks like.
foreach ($district_ward as $key => $value) {
$ward_ids = array_keys($district_ward[$key]);
for ($x = 0; $x < count($ward_ids); $x++) {
echo $key;
$district_village[$key]= array_merge($value[$ward_ids[$x]], $value[$ward_ids[$x+1]]);
}
}
Should do the trick, this because you start at 0 up UNTIL the amount of $ward_ids
Let's say your $ward_ids has 1 entry, then you would have looped 0 till 0, so no loops at all,
And lets say it had 102 entries, then you would have looped 1-101, leaving 102 out since you started at 0.