PHP - Sequence through array and repeat [modulo-operator] - php

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";
}

Related

Divide/Split an array into two arrays one with even numbers and other with odd numbers

Please see my script, and identify the issue. Trying to Split an array into two arrays by value even or odd without built-in functions in PHP
<?php
$array = array(1,2,3,4,5,6);
$length = count($array);
$even = array();
for($i=0; $i < $length; $i++){
if($array[$i]/2 == 0){
$even[] = $array[$i];
}
else{
$odd[] = $array[$i];
}
}
print_r($even);
echo "<br/>";
print_r($odd);
?>
current output
Array ( )
Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 )
Your error is in if condition, you want to check if the number is odd or even, you have to use modulus % operator. So your code becomes like this
<?php $array = array(1,2,3,4,5,6);
$length = count($array);
$even = array();
for($i=0; $i < $length; $i++){
if($array[$i]%2 == 0){
$even[] = $array[$i];
}
else{
$odd[] = $array[$i];
}
}
print_r($even);
echo "<br/>";
print_r($odd);
Try the modulo % operator when you check for even numbers. It gets the remainder when you divide your value by 2.
if($array[$i] % 2 == 0)
Your current code divides your value by 2 then gets the quotient, that's why it doesn't equate to 0. 2/2 = 1 4/2 = 2 and so on...
Hope this helps.

Nested loop logic

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 .

PHP replace every 2nd

<?php
$fact_BB = array("[start]", "[mid]", "[end]");
$fact_HTML = array("<tr><td class='FactsTableTDOne'><p>", "</p></td><td class='FactsTableTDTwo'><p>", "</p></td></tr>");
$str_Facts = str_replace($fact_BB, $fact_HTML, $row['facts']);
echo $str_Facts;
?>
Is it possible to switch between 2 $fact_HTML?
1. $fact_HTMLone = "code";
2. $fact_HTMLtwo = "code";
3. $fact_HTMLone = "code";
4. $fact_HTMLtwo = "code";
5. $fact_HTMLone = "code";
etc. etc.
Sure. With $fact_HTML[0], $fact_HTML[1], $fact_HTML[n] etc. you can access your $fact_HTML array. Using modulo of 2 you can always access every 2nd (or first and second) elements of the array.
To check if the element is even or odd you can use:
if ($n % 2 == 0) {
//even element
} else {
//odd element
}
Also you can use Modulo 2 ($n % 2) as n to iterate through the array in the same way. You can also combine both variants.
$count = 10; //number of facts
for ($n = 0; $n < $count; $n++) {
$fact_HTML[$n % 2] = $fact;
}
What you want to achieve is a replace of some strings. I'd suggest a solution like this:
<?php
$str_Facts = $row['facts'];
$replacements = array( "[start]" => "<tr><td class='FactsTableTDOne'><p>",
"[mid]" => "</p></td><td class='FactsTableTDTwo'><p>",
"[end]" => "</p></td></tr>" );
foreach ($replacements as $repkey => $repval) {
$str_Facts = str_replace($repkey,$repval,$str_Facts);
}
echo $str_Facts;
?>
If you want to go on with your approach, you'd loop through the arrays (you have to ensure that the both arrays have the same number of elements).
<?php
$str_Facts = $row['facts'];
for ($i=0;$i<count($fact_BB);$i++) {
//if you want to switch every uneven, do this:
if ($i%2!=0) continue;
$str_Facts = str_replace($fact_BB[$i],$fact_HTML[$i],$str_Facts);
}
echo $str_Facts;
?>

PHP Count 1 too many on Array as it's 0 based?

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.

Given an array of integers, what's the most efficient way to get the number of other integers in the array within n?

Given the following array:
$arr = array(0,0,1,2,2,5,6,7,7,9,10,10);
And assuming $n = 2, what is the most efficient way to get a count of each value in the array within $n of each value?
For example, 6 has 3 other values within $n: 5,7,7.
Ultimately I'd like a corresponding array with simply the counts within $n, like so:
// 0,0,1,2,2,5,6,7,7,9,10,10 // $arr, so you can see it lined up
$count_arr = array(4,4,4,4,4,3,3,4,4,4, 2, 2);
Is a simple foreach loop the way to go? CodePad Link
$arr = array(0,0,1,2,2,5,6,7,7,9,10,10);
$n = 2;
$count_arr = array();
foreach ($arr as $v) {
$range = range(($v-$n),($v+$n)); // simple range between lower and upper bound
$count = count(array_intersect($arr,$range)); // count intersect array
$count_arr[] = $count-1; // subtract 1 so you don't count itself
}
print_r($arr);
print_r($count_arr);
My last answer was written without fully groking the problem...
Try sorting the array, before processing it, and leverage that when you run through it. This has a better runtime complexity.
$arr = array(0,0,1,2,2,5,6,7,7,9,10,10);
asort($arr);
$n = 2;
$cnt = count($arr);
$counts = array_pad(array(), $cnt, 0);
for ($x=0; $x<$cnt; $x++) {
$low = $x - 1;
$lower_range_bound = $arr[$x]-$n;
while($low >= 0 && ($arr[$low] >= $lower_range_bound)) {
$counts[$x]++;
$low--;
}
$high = $x + 1;
$upper_range_bound = $arr[$x]+$n;
while($high < $cnt && $arr[$high] <= $upper_range_bound) {
$counts[$x]++;
$high++;
}
}
print_r($arr);
print_r($counts);
Play with it here: http://codepad.org/JXlZNCxW

Categories