I am needing to add a different class at the end of every 4th item that I am looping through. I have done so by:
$i=0;
foreach($mount as $m){
$i++;
$startClass = '';
if($i==4||$i==8||$i==12){$startClass='<div with class>';} //adds class on 4th intervals
$ret.=''.$startClass.'<other HTML here and such>'; //shorted for readability
}
Now I'm sure there is a more appropriate way to handle this given the fact that if my loop contains 40 objects, I'll need to adjust the if statement accordingly.
I'm recalling an arithmetic formula that might work [an = a1+(n-1)d] but I'm finding that my idea seems off. I apply it (replacing an with i) and it will always = to the equation, thus each item gets the class.
Any suggestions? Thanks in advance!
Use the modulus operator
http://www.php.net/manual/en/language.operators.arithmetic.php
if(($i % 4) === 0){
//add class
}
what you are looking for is modulo operator
example:
if($i%4 == 0){$startClass='<div with class>';}
which means that i = k + 0, k being integer
A combination of the foreach control structure and the % modulus operator will give you what you need:
foreach ($mount as $key => $m) {
if ($key % 4 == 0) {
$startClass = '<div with class>';
} else {
$startClass = '';
}
$ret.=''.$startClass.'<other HTML here and such>';
}
The foreach hash-rocket (=>) notation enables you to pass the index of the current element being iterated through. You can use the index to keep track of the nth-object.
The modulus operator returns the remainder from division; if the remainder is zero, the divisor is a factor of the dividend and thus can be used to calculate nth-factors.
$i=0;
foreach($mount as $m)
{
if (($i++ % 4) == 0)
{
}
}
Related
My code is:
$count=0;
foreach( $List AS $email){
$data = my_function($url);
$count++;
if(filter_var($email , FILTER_VALIDATE_EMAIL)){
...............
my_function runs a simple cURL for an url and returns session_id and api_identity as results. If I run it in the loop for each email in the list, my code is very slow and takes time to show results.
now
$data = my_function($url);
Is applied for each email.
My question:
Is there any way to apply $data = my_function($url); for every 10th mail in the whole list?
If I'm not misunderstanding your question, you want to do something every nth iteration, which can be accomplished using modulo operators:
$count = 1;
foreach ($List as $email)
{
if ($count % 10 == 0) $data = my_function($url);
$count++;
...
}
If you don't know what x % y does, it simply returns the remainder of the expression x/y. A simple trick is therefore to use the fact that when evaluating x % n for different values x = 1, 2, 3..., the same result will repeat every nth time.
Note that depending on what your counter starts at, you will get a different start-email. If you keep it 0 as you have now, the function will be called for the 1st, 11th, 21st, .... emails. If you change it to 1 as I did, the first email for which the function will be called is the 10th one.
You can use https://stackoverflow.com/a/44883380/7095134 this answer or by using counter variable you can achieve that.
e.g:
counter=0;
for(i=0; i<=100; i++)
{
if(counter==10){ counter=0; call_your_function(); }
else { do the rest of work; counter++ ;}
}
I have a large form, which when submitted to the database, it needs splitting into odd and even (based on their HTML name), so I can perform a calculation on them.
There are 120 total HTML Input fields, so 60 odd and 60 even.
The for loops that iterates through them are:
$h=0; $o=0;
for($i=1; $i<=119; $i+=2)
{
$h = $h + Input::get($i);
}
for($i=2; $i<=120; $i+=2)
{
$o = $o + Input::get($i);
}
What I am finding is that the odd number for loop is working correctly, but even though the second loop begins at 2, it is skipping adding that Input::get($i); and moving onto the 4th input.
If I echo the odd for loop, it outputs (with all the input values at 1):
for($i=2; $i<=120; $i+=2)
{
echo $i;
echo (",");
$o = $o + Input::get($i);
echo (Input::get($i));
}
2,14,16,18,110,112,114,116,118,
So as you can see, it isn't picking up the '1' value from the 2nd input field.
Any help as to why this is would be greatly appreciated.
You do not need two loops to accomplish this, use the modulo math function to determine if there is a remainder of 0 when dividing by 2 (indicating an even number), try this out:
for($i=0; $i<=120; $i++)
{
if($i%2 == 0) //even
$o = $o + Input::get($i);
else //odd
$h = $h + Input::get($i);
}
You should make a single loop that iterates from 1 to 120. Then test if the counter is odd/even using the modulus operator ($a % $b).
i.e. if $a % 2 = 0 then the value is even else it is odd.
I have a comma delimited list of numbers which i am converting into an array and what i want to know about the list of numbers is if the numbers listed obey a natural ordering of numbers,you know,have a difference of exactly 1 between the next and the previous.
If its true the list obeys the natural ordering,i want to pick the first number of the list and if not the list obeys not the natural order,i pick the second.
This is my code.
<?php
error_reporting(0);
/**
Analyze numbers
Condition 1
if from number to the next has a difference of 1,then pick the first number in the list
Condition 2
if from one number the next,a difference of greater than 1 was found,then pick next from first
Condition 3
if list contains only one number,pick the number
*/
$number_picked = null;
$a = '5,7,8,9,10';
$b = '2,3,4,5,6,7,8,9,10';
$c = '10';
$data = explode(',', $b);
$count = count($data);
foreach($data as $index => $number)
{
/**
If array has exactly one value
*/
if($count == 1){
echo 'number is:'.$number;
exit();
}
$previous = $data[($count+$index-1) % $count];
$current = $number;
$next = $data[($index+1) % $count];
$diff = ($next - $previous);
if($diff == 1){
$number_picked = array_values($data)[0];
echo $number_picked.'correct';
}
elseif($diff > 1){
$number_picked = array_values($data)[1];
echo $number_picked.'wrong';
}
}
?>
The problem i am having is to figure out how to test the difference for all array elements.
No loops are needed, a little bit of maths will help you here. Once you have your numbers in an array:
$a = explode(',', '5,7,8,9,10');
pass them to this function:-
function isSequential(array $sequence, $diff = 1)
{
return $sequence[count($sequence) - 1] === $sequence[0] + ($diff * (count($sequence) - 1));
}
The function will return true if the numbers in the array follow a natural sequence. You should even be able to adjust it for different spacings between numbers, eg 2, 4, 6, 8, etc using the $diff parameter, although I haven't tested that thoroughly.
See it working.
Keep in mind that this will only work if your list of numbers is ordered from smallest to largest.
Try using a function to solve this... Like so:
<?php
error_reporting(0);
/**
Analyze numbers
Condition 1
if from number to the next has a difference of 1,then pick the first number in the list
Condition 2
if from one number the next,a difference of greater than 1 was found,then pick next from first
Condition 3
if list contains only one number,pick the number
*/
$number_picked = null;
$a = '5,7,8,9,10';
$b = '2,3,4,5,6,7,8,9,10';
$c = '10';
function test($string) {
$data = explode(',', $string);
if(count($data) === 1){
return 'number is:'.$number;
}
foreach($data as $index => $number)
{
$previous = $data[($count+$index-1) % $count];
$current = $number;
$next = $data[($index+1) % $count];
$diff = ($next - $previous);
if($diff == 1){
$number_picked = array_values($data)[0];
return $number_picked.'correct';
}
elseif($diff > 1){
$number_picked = array_values($data)[1];
return $number_picked.'wrong';
}
}
}
echo test($a);
echo test($b);
echo test($c);
?>
You already know how to explode the list, so I'll skip that.
You already handle a single item, so I'll skip that as well.
What is left, is checking the rest of the array. Basically; there's two possible outcome values: either the first element or the second. So we'll save those two first:
$outcome1 = $list[0];
$outcome2 = $list[1];
Next, we'll loop over the items. We'll remember the last found item, and make sure that the difference between the new and the old is 1. If it is, we continue. If it isn't, we abort and immediately return $outcome2.
If we reach the end of the list without aborting, it's naturally ordered, so we return $outcome1.
$lastNumber = null;
foreach( $items as $number ) {
if($lastNumber === null || $number - $lastNumber == 1 ) {
// continue scanning
$lastNumber = $number;
}
else {
// not ordened
return $outcome2;
}
}
return $outcome1; // scanned everything; was ordened.
(Note: code not tested)
To avoid the headache of accessing the previous or next element, and deciding whether it still is inside the array or not, use the fact that on a natural ordering the item i and the first item have a difference of i.
Also the corner case you call condition 3 is easier to handle outside the loop than inside of it. But easier still, the way we characterize a natural ordered list holds for a 1-item list :
$natural = true;
for($i=1; $i<$count && $natural; $i++)
$natural &= ($data[$i] == $data[0] + $i)
$number = $natural ? $data[0] : $data[1];
For $count == 1 the loop is never entered and thus $natural stays true : you select the first element.
for($i=0;$i<$num;$i++) {
if($i==even) $hilite="hilite";
dothing($i,$hilite);
}
This is basically what I want to accomplish.
What is the most efficient way to determine if $i is even?
I know I could check if half == mod 2 ... but that seems a little excessive on the calculations? Is there a simpler way?
if ($i % 2 == 0)
The already mentioned % 2 syntax is most used, and most readable for other programmers. If you really want to avoid an 'overhead' of calculations:
for($i = 0, $even = true; $i < $num; $i++, $even =! $even) {
if($even) $hilite = "hilite";
dothing($i,$hilite);
}
Although the assignment itself is probably more work then the '%2' (which is inherently just a bit-shift).
It doesn't get any simpler than $i % 2 == 0. Period.
Change the i++ in the loop statement to i+=2, so that you only examine even values of i?
Typically, a number is odd if it's LSB (Least Significant Bit) is set. You can check the state of this bit by using the bitwise AND operator:
if($testvar & 1){
// $testvar is odd
}else{
// $testvar is even
}
In your code above, a more efficient way would be to have $i increment by 2 in every loop (assuming you can ignore odd-values):
for($i=0;$i<$num;$i+=2){
// $i will always be even!
}
I'm working on custom pagination system and encountered following problem. When one of the elements is filtered out of the set, the size of the final array is smaller than needed. Therefore I'm looking for a solution to increase the number of iterations from within the loop to always get array consisting of 50 elements.
$limit = 50; //Number of elements I want to fetch
for($x=0; $x<$limit; $x++){
if ($elementIsNotFiltered) {
//add element to $someArray;
}
else {
//increase the number of iterations, so even if some elements are filtered out,
//the size of $someArray will always be 50
}
}
Thanks for any help.
Do it in a while() loop instead, and break when you finally hit your $limit
Use a while loop.
while(count($somearray) < 50 && /*elements remain*/) ...
else {
++$limit;
}
Tried that?
You may also do the same thing the other way round:
else {
--$x;
}
Or be a little bit more effective:
$x = 0;
while ($x != 50) {
if ($notFiltered) {
++$x;
}
}
If you want to save the counter variable, too, you may use:
while (!isset($array[49])) {
}
The !isset($array[49]) here is only a synonym of count($array) < 50.
It sounds to me like you're looking for a while loop - not a for loop:
while ($items < 50 && [more items to filter]) {
if ([add to array]) {
$items++;
}
}
If you really want to do it in your for loop you can always modify $x but this makes your code unreadable and hard to maintain - I would recommend not doing this...