Show next and previous keys of an array with cycling - php

I'm sure you're gonna like it ;).
I need a function for building navigation for browsing pages in a book (where some pages could have been reaped apart and it should cycle back and forth); it should output links( as numbers) to the "next" and "previous" pages of the given page.
Function that will receive an array and a key on input should spit out the value of the given key of the array as well as a value of "next" and "previous" values. However if the given key is the first key in the array it should output last key of an array as "previous". Likewise, if it receives the last key, it should output the first key as "next".
Here's what I have so far:
$pages = array(5, 1, 6, 8);
sort($pages);
$selected = 1; // that's second key (value:5, next:6, previous:1)
// $selected = 3; // that's forth and a last key (value:8, should return next:1, previous:6)
$selected = key($pages)+$selected;
while ($pointer = current($pages)) {
if ($selected == key($pages) ) {
echo $pointer." - current <br>";
}
elseif($selected+1 == key($pages) ){
echo $pointer." - next <br>";
}
elseif($selected-1 == key($pages) ){
echo $pointer." - previous <br>";
}
else
echo $pointer."<br>";
next($pages);
}
THis should actually work (but without 'cycle awarness') - you can check quickly in http://writecodeonline.com/php/- if the description confuses you, output of this code is quite self explanatory...
I believe it's quite easy, but I'm out of ideas and it's 3 o'clock in the morning. Of course I need most simple solution, so ther could be some easier way, than the one I've chosen.

I think this is solution of your problem. Tell me if it's doing what you want (Some checking if you're going out of array bounds will be good :) but let's stick to simplicity...):
/* This is from your code */
$pages = array(5, 1, 6, 8);
sort($pages);
$selected = 1; // that's second key (value:5, next:6, previous:1)
$selected = 3; // that's forth and a last key (value:8, should return next:1, previous:6)
/* ... */
$pages_count = count($pages);
$pages_ordered = array();
$pages_ordered["current"] = $pages[$selected];
foreach($pages as $order_number => $page)
{
if($selected == 0) {
$pages_ordered["previous"] = $pages[$pages_count - 1];
$pages_ordered["next"] = $pages[$selected + 1];
} elseif($selected == ($pages_count - 1)) {
$pages_ordered["next"] = $pages[0];
$pages_ordered["previous"] = $pages[$selected - 1];
} else {
$pages_ordered["next"] = $pages[$selected + 1];
$pages_ordered["previous"] = $pages[$selected - 1];
}
}
print_r($pages_ordered);

It really is pretty simple to be honest.
$pages = array(5, 1, 6, 8);
sort($pages);
//how many pages do we have
$total = count($pages);
//replace with $_GET['page']; when ready
$requested_page = rand(0, ($total -1)); //$_GET['page'];
//the selected page
$selected = $pages[$requested_page];
//if this isn't the first page
if($selected != $pages[0]):
//get the previous page
$prev = $requested_page-1;
//standard issue
echo '<a style="margin:0 15px;" href="myscript.php?page=', $pages[$prev] ,'"> Previous </a>';
endif;
//iterate each page
foreach($pages as $page):
//a ternary operator to assign a class if this is the current page we're on or not
$cls = ($page == $selected ) ? 'active' : false; //for your current page class
//you don't need the style
echo '<a class="', $cls ,'" href="myfile.php?page=', $page ,'">', $page ,'</a>';
endforeach;
//if this is not the last page
if(selected != $pages[$total]):
//our next page
$next = $requested_page+1;
//standard issue
echo ' Next ';
endif;

Try this function
function get_nav($arr,$current){
while($nav = current($arr)){
if(key($arr)==$current){
$prev =prev($arr);
empty($prev)?reset($arr):'';
next($arr);
$r = current($arr);
$next = next($arr);
prev($arr);
return array('prev'=>$prev,'current'=>$r,'next'=>$next);
}
next($arr);
}
return FALSE;
}
$pages = array(5, 1, 6, 8);
sort($pages);
$selected = 0;
$res = get_nav($pages,$selected);

Related

Auto increment function does not accept 0 as starting number

I created a small function that helps me build an array (i use it to populate a select2 element). It works great but it doesn't accept 0 as the starting number.
Although it is not really crucial i would really want to understand why this happens and how to fix it.
Here is the function:
function create_numstring_array($startNum, $endNum, $jumps, $sideString = NULL) {
if($startNum && $endNum) {
$data = array();
$counter = intval($startNum);
while($endNum > $counter ) {
$data["$counter"] = $counter.' '.$sideString;
$counter = $counter + $jumps;
// echo $counter."<br />";
}
return $data;
}
}
/* DOESNT WORK
echo '<pre>Code:'."<br />";
print_r(create_numstring_array(0, 9, 0.5, ''));
echo '</pre>'."<br />";
*/
/* WORKS! */
echo '<pre>Code:'."<br />";
print_r(create_numstring_array(1, 9, 0.5, ''));
echo '</pre>'."<br />";
I guess it gets stuck in this part
while($endNum > $counter) {
Since $counter = 0 but how can i overcome this?
Because (bool)0 == False. So, your code fails, because you are testing $startNum and it is treated as boolean false.
Change it to something more reasonable, for example: if (is_int($startNum) ... or functions like that (is_numeric could be candidate)
function create_numstring_array($startNum, $endNum, $jumps, $sideString = NULL){
#check for valid input
#(can be float or integer so lets end always greater than start)
if($startNum>$endNum || !is_numeric($jumps)) {
return null;
}
#create the range
$keys = range($startNum, $endNum, $jumps);
#create values with or without sideString
$values = ($sideString)
? array_map(function($a) use ($sideString){ return $a.' '.$sideString;},$keys)
: $keys;
#return the new array
return array_combine($keys,$values);
}
echo '<pre>Code:'."<br />";
print_r(create_numstring_array(0, 9, 0.5, ''));
echo '</pre>'."<br />";
Why your version is not working, is explained in the comments, so here a working version, that check for valid input and valid jumbs. (Works with float and integer). Remove/Skipp last and first entry is they are not needed.

show unique links from array

I have a function that shows a random banner from array:
//func.php
function rand_rek($rek_array){
$numberOfBanners = count($rek_array);
$numberOfBanners = $numberOfBanners - 1;
$randomBanner = rand(0,$numberOfBanners);
$rek = $rek_array[$randomBanner];
return $rek;
}
I have $reklamas array, that contains 3 banners:
//ads.php
$reklamas = array($rek1, $rek2, $rek3);
if $_GET["noa"] isnt true, I want to add more banners to $reklamas array:
if (!isset($_GET["noa"]))
array_push($reklamas, $rek_adc1, $rek_adc2, $rek_adc3, $rek_adc4);
And I want to display one of random banners x times:
for ($i=0;$i<$banneri;$i++) {
echo rand_rek($reklamas);
}
The problem:
These can be repeated as many times as they want array($rek1, $rek2, $rek3);,
while these array_push($reklamas, $rek_adc1, $rek_adc2, $rek_adc3, $rek_adc4); can be each showed only 1 time.
function rand_rek() is in func.php and it is being included from ads.php where is the rest of the code.
I think you're probably going about the problem all wrong, but in any case a solution could be
function rand_rek($rek_array){
$numberOfBanners = count($rek_array);
$numberOfBanners = $numberOfBanners - 1;
$randomBanner = rand(0,$numberOfBanners);
$rek = $rek_array[$randomBanner];
return [$randomBanner, $rek];
}
list($bannerNum, $banner) = rand_rek($reklamas);
if ($bannerNum < 3) {
$repeats = $x;
} else {
$repeats = 1;
}
for ($i=0;$i<$repeats;$i++) {
echo $banner;
}
Which retrieves the index of the banner and checks it before running the loop. I've also used your value $x that you mention in the text but not in your code.

Calculate closest matches from array value combinations

I have an array of part lengths, for examples sake:-
array(150, 180, 270);
I then have a measurement ($a = 440)
I need to calculate the two closest possible combinations of lengths which are greater than $a without manually having to write hundreds of possible combinations in order to work it out.
So:
150
180
270
150 + 150
150 + 180
150 + 270
180 + 180
180 + 270
270 + 270
150 + 150 + 150
150 + 150 + 180
..and so on.
This will need to run for a set number of times, rather than just finding the first two matches and stopping, as 150 + 150 + 150 would be a closer match to $a than 270 + 270 but may run after.
edit: I also need to store the combination of parts which made up the match, preferably in an array.
I hope I've explained this well enough for somebody to understand.
As this is quite a resource heavy script, I thought it would be a good idea to give the option to generate the choices beforehand, then use that data to create a variable/object/sql script to permanently store the data. For instance, doing something like
SELECT * FROM combination_total WHERE size > YOUR_SIZE ORDER BY size ASC LIMIT 2;
The new script I have is similar, but it just generates an array of all combinations without any duplicates. Seems pretty quick again. Notice the $maxLength variable, which is currently set to 2000, which can be modified with your own largest possible size.
<?php
$partLengths = array(150, 180, 270);
$currentCombinations = array(
array(
'total' => 150,
'combination' => array(150)
),
array(
'total' => 180,
'combination' => array(180)
),
array(
'total' => 270,
'combination' => array(270)
)
);
$maxLength = 2000;
$largestSize = 0;
function generateCombination() {
global $currentCombinations, $largestSize, $partLengths;
$tmpCombinations = $currentCombinations;
foreach ($tmpCombinations as $combination) {
foreach ($partLengths as $partLength) {
$newCombination = $combination['combination'];
$newCombination[] = $partLength;
sort($newCombination);
$newCombinationTotal = array_sum($newCombination);
if (!combinationExists($newCombination)) {
$currentCombinations[] = array(
'total' => $newCombinationTotal,
'combination' => $newCombination
);
}
$largestSize = ($newCombinationTotal > $largestSize) ? $newCombinationTotal : $largestSize;
}
}
}
function combinationExists($combination) {
global $currentCombinations;
foreach ($currentCombinations as $currentCombination) {
if ($combination == $currentCombination['combination']) {
return true;
}
}
return false;
}
while ($largestSize < $maxLength) {
generateCombination();
}
// here you can use $currentCombinations to generate sql/object/etc
var_dump($currentCombinations);
?>
This code works out the closest combination above $a, and the next closest one after that. It removes duplicates to speed things up a bit. It's not mega-optimized but initial tests show it's not too bad, depending on the initial value of $a not being massive.
<?php
/* value in cm */
$a = 1020;
$partLengths = array(150, 180, 270);
$closestValue = array();
$secondClosest = array();
$currentCombinations = array(
array(
'total' => 150,
'combination' => array(150)
),
array(
'total' => 180,
'combination' => array(180)
),
array(
'total' => 270,
'combination' => array(270)
)
);
function getCombinations(&$currentCombinations, $partLengths,$a, &$closestValue, &$secondClosest) {
$tmpCombinations = $currentCombinations;
static $secondMatch = true;
for ($x=0;$x<count($partLengths);$x++) {
for ($y=0;$y<count($tmpCombinations);$y++) {
$newCombination = $tmpCombinations[$y]['combination'];
$newCombination[] = $partLengths[$x];
$newCombinationTotal = array_sum($newCombination);
sort($newCombination);
if (!combinationExists($currentCombinations, $newCombination, $newCombinationTotal)) {
$currentCombinations[] = array('total' => $newCombinationTotal, 'combination' => $newCombination);
}
if ($closestValue['total'] < $a) {
$oldGap = $a - $closestValue['total'];
$newGap = $a - $newCombinationTotal;
$newGap = ($newGap < 0) ? 0 - $newGap : $newGap;
if ($newGap < $oldGap) {
$secondClosest = $closestValue;
$closestValue['total'] = $newCombinationTotal;
$closestValue['combination'] = $newCombination;
}
} else {
$oldGap = $a - $secondClosest['total'];
$newGap = $a - $newCombinationTotal;
$oldGap = ($oldGap < 0) ? 0 - $oldGap : $oldGap;
$newGap = ($newGap < 0) ? 0 - $newGap : $newGap;
if ($newCombinationTotal > $a && $newCombinationTotal > $closestValue['total']) {
if ($secondMatch || $newGap < $oldGap) {
$secondMatch = false;
$secondClosest['total'] = $newCombinationTotal;
$secondClosest['combination'] = $newCombination;
}
}
}
}
}
}
function combinationExists(&$currentCombinations, $newCombination, $newCombinationTotal) {
foreach ($currentCombinations as $currentCombination) {
if ($currentCombination['total'] != $newCombinationTotal && $currentCombination['combination'] != $newCombination) {
return false;
}
}
return false;
}
while ($secondClosest['total'] <= $a) {
getCombinations($currentCombinations, $partLengths, $a, $closestValue, $secondClosest);
}
var_dump($closestValue);
var_dump($secondClosest);
?>
A further suggestion, if speed does become an issue, is to pre generate all combinations and save them in some kind of hash/database/etc that you can easily access.
The following code is brute-force and tests only possible combinations of 2 values, so I know it's not complete. However, it is a start.
UPDATE: See my other answer, below, for a far better solution that works with any possible combination, not just 2, and that is optimized.
<?php
echo "<html><head><title>Test Array Sums</title></head><body>";
$testarray = array(2, 5, 9, 78, 332);
$target_value = 10;
$closest1 = 0;
$closest2 = 0;
$closest_sum = 0;
$closest_difference = 0;
$first_time_in_loop = TRUE;
foreach ($testarray AS $entry1)
{
foreach ($testarray AS $entry2)
{
if ($first_time_in_loop)
{
$first_time_in_loop = FALSE;
$closest1 = $entry1;
$closest2 = $entry2;
$closest_sum = $closest1 + $closest2;
$closest_difference = abs($target_value - $closest_sum);
}
$test_sum = $entry1 + $entry2;
if (abs($test_sum - $target_value) < $closest_difference)
{
if ($test_sum - $target_value >= 0)
{
// Definitely the best so far
$closest1 = $entry1;
$closest2 = $entry2;
$closest_sum = $closest1 + $closest2;
$closest_difference = abs($closest_sum - $target_value);
}
else if ($closest_sum - $target_value < 0)
{
// The sum isn't big enough, but neither was the previous best option
// and at least this is closer
$closest1 = $entry1;
$closest2 = $entry2;
$closest_sum = $closest1 + $closest2;
$closest_difference = abs($closest_sum - $target_value);
}
}
else
{
if ($closest_sum - $target_value < 0 && $test_sum - $target_value >= 0)
{
// $test_value is farther away from the target than the previous best option,
// but at least it's bigger than the target value (the previous best option wasn't)
$closest1 = $entry1;
$closest2 = $entry2;
$closest_sum = $closest1 + $closest2;
$closest_difference = abs($closest_sum - $target_value);
}
}
}
}
echo "Best pair: " . $closest1 . ", " . $closest2 . "<br />";
echo "</body></html>";
?>
Can you limit the total number of test values to 3 - or some larger number - or do you truly need to extend it to all possible combinations (i.e. if 4+4+5+4+4+5+3+5+4+5+3+4 is closer than 26+26, than you need to find it?)
If you can limit the number being tested to, say, 5, then you could just extend the loop above to handle up to 5 choices. Otherwise, a more sophisticated loop would need to be written.
Improving on my previous answer, here is a version that works to test any number of entries, up to a maximum number.
UPDATE: (Optimization added; see comments below)
For example, if the desired value is 15, and the list is (1, 17, 20), the best choice is 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1, so you would have to allow $max_loops, below, to be at least 15 in order to find this match - even though there are only 3 values in the list! It's worse for (1, 133, 138) where the desired value is, say, 130. In that case, you need 130 recursions! You can see that this is could be an optimization nightmare. But, the below algorithm works and is fairly well optimized.
<?php
echo "<html><head><title>Test Array Sums</title></head><body>";
$testarray = array(1, 3, 6);
$target_value = 10;
$current_closest_sum = 0;
$current_closest_difference = 0;
$first_time_in_loop = TRUE;
$max_loops = 10;
$current_loop = 0;
$best_set = array();
$current_set = array();
$sums_already_evaluated = array();
function nestedLoop($current_test = 0)
{
global $testarray, $target_value, $current_closest_sum, $current_closest_difference, $first_time_in_loop, $max_loops, $current_loop, $best_set, $current_set, $sums_already_evaluated;
++$current_loop;
foreach ($testarray AS $entry)
{
$current_set_temp = $current_set;
$current_set[] = $entry;
if ($first_time_in_loop)
{
$first_time_in_loop = FALSE;
$current_closest_sum = $entry + $current_test;
$current_closest_difference = abs($target_value - $current_closest_sum);
$best_set[] = $entry;
}
$test_sum = $entry + $current_test;
if (in_array($test_sum, $sums_already_evaluated))
{
// no need to test a sum that has already been tested
$current_set = $current_set_temp;
continue;
}
$sums_already_evaluated[] = $test_sum;
if ($test_sum > $target_value && $current_closest_sum > $target_value && $test_sum >= $current_closest_sum)
{
// No need to evaluate a sum that is certainly worse even by itself
$current_set = $current_set_temp;
continue;
}
$set_best = FALSE;
if (abs($test_sum - $target_value) < $current_closest_difference)
{
if ($test_sum - $target_value >= 0)
{
// Definitely the best so far
$set_best = TRUE;
}
else if ($current_closest_sum - $target_value < 0)
{
// The sum isn't big enough, but neither was the previous best option
// and at least this is closer
$set_best = TRUE;
}
}
else
{
if ($current_closest_sum - $target_value < 0 && $test_sum - $target_value >= 0)
{
// $test_value is farther away from the target than the previous best option,
// but at least it's bigger than the target value (the previous best option wasn't)
$set_best = TRUE;
}
}
if ($set_best)
{
$current_closest_sum = $test_sum;
$current_closest_difference = abs($current_closest_sum - $target_value);
$best_set = $current_set;
}
if ($current_loop < $max_loops)
{
if ($test_sum - $target_value < 0)
{
nestedLoop($test_sum);
}
}
$current_set = $current_set_temp;
}
--$current_loop;
}
// make array unique
$testarray = array_unique($testarray);
rsort($testarray, SORT_NUMERIC);
// Enter the recursion
nestedLoop();
echo "Best set: ";
foreach ($best_set AS $best_set_entry)
{
echo $best_set_entry . " ";
}
echo "<br />";
echo "</body></html>";
?>
UPDATE: I have added two small optimizations that seem to help greatly, and avoid the memory overload or hash-table lookup. They are:
(1) Track all previously evaluated sums, and do not evaluate them again.
(2) If a sum is (by itself) already worse than a previous test, skip any further tests with that sum.
I think, with these two optimizations, the algorithm may work quite well for realistic use in your situation.
PREVIOUS COMMENTS BELOW, NOW SOMEWHAT IRRELEVANT
My previous comments, below, are somewhat moot because the above two optimizations do seem to work quite well. But I include the comments anyways.
Unfortunately, as noted, the above loop is HIGHLY non-optimized. It would have to be optimized in order to work in a realistic situation, by avoiding duplicate tests (and other optimizations). However, it demonstrates an algorithm that works.
Note that this is a complex area mathematically. Various optimizations might help in one scenario, but not another. Therefore, to make the above algorithm work efficiently, you would need to discuss realistic usage scenarios - Will there be a limit on the largest length in the list of parts? What is the range of lengths? And other, more subtle features of the parts list & desired goal, though subtle, are likely to make a big difference in how to go about optimizing the algorithm.
This is a case where the "theoretical" problem isn't sufficient to yield a desired solution, since optimization is so critically important. Therefore, it's not particularly useful to make optimization suggestions.
Leonard's optimization, for example, (avoiding duplicates by saving all combinations previously tested) works well for a small-ish set, but the memory usage would explode for larger sets (as he noted). It's not a simple problem.
(code edited ~2 hours later to handle possible missed combination due to limiting the recursion to a certain number of recursions - by sorting the array from high to low, initially)

PHP loops to check that a set of numbers are consecutive

I'm trying to loop through a set of records, all of which have a "number" property. I am trying to check if there are 3 consecutive records, e.g 6, 7 and 8.
I think i'm almost there with the code below, have hit the wall though at the last stage - any help would be great!
$nums = array();
while (count($nums <= 3))
{
//run through entries (already in descending order by 'number'
foreach ($entries as $e)
{
//ignore if the number is already in the array, as duplicate numbers may exist
if (in_array($e->number, $num))
continue;
else
{
//store this number in the array
$num[] = $e->number;
}
//here i need to somehow check that the numbers stored are consecutive
}
}
function isConsecutive($array) {
return ((int)max($array)-(int)min($array) == (count($array)-1));
}
You can achieve the same result without looping, too.
If they just have to be consecutive, store a $last, and check to make sure $current == $last + 1.
If you're looking for n numbers that are consecutive, use the same, except also keep a counter of how many ones fulfilled that requirement.
$arr = Array(1,2,3,4,5,6,7,343,6543,234,23432,100,101,102,103,200,201,202,203,204);
for($i=0;$i<sizeof($arr);$i++)
{
if(isset($arr[$i+1]))
if($arr[$i]+1==$arr[$i+1])
{
if(isset($arr[$i+2]))
if($arr[$i]+2==$arr[$i+2])
{
if(isset($arr[$i+3]))
if($arr[$i]+3==$arr[$i+3])
{
echo 'I found it:',$arr[$i],'|',$arr[$i+1],'|',$arr[$i+2],'|',$arr[$i+3],'<br>';
}//if3
}//if 2
}//if 1
}
I haven't investigated it thoroughly, maybe can be improved to work faster!
This will confirm if all items of an array are consecutive either up or down.
You could update to return an array of [$up, $down] or another value instead if you need direction.
function areAllConsecutive($sequence)
{
$up = true;
$down = true;
foreach($sequence as $key => $item)
{
if($key > 0){
if(($item-1) != $prev) $up = false;
if(($item+1) != $prev) $down = false;
}
$prev = $item;
}
return $up || $down;
}
// areAllConsecutive([3,4,5,6]); // true
// areAllConsecutive([3,5,6,7]); // false
// areAllConsecutive([12,11,10,9]); // true
Here's an example that can check this requirement for a list of any size:
class MockNumber
{
public $number;
public function __construct($number)
{
$this->number = $number;
}
static public function IsListConsecutive(array $list)
{
$result = true;
foreach($list as $n)
{
if (isset($n_minus_one) && $n->number !== $n_minus_one->number + 1)
{
$result = false;
break;
}
$n_minus_one = $n;
}
return $result;
}
}
$list_consecutive = array(
new MockNumber(0)
,new MockNumber(1)
,new MockNumber(2)
,new MockNumber(3)
);
$list_not_consecutive = array(
new MockNumber(5)
,new MockNumber(1)
,new MockNumber(3)
,new MockNumber(2)
);
printf("list_consecutive %s consecutive\n", MockNumber::IsListConsecutive($list_consecutive) ? 'is' : 'is not');
// output: list_consecutive is consecutive
printf("list_not_consecutive %s consecutive\n", MockNumber::IsListConsecutive($list_not_consecutive) ? 'is' : 'is not');
// output: list_not_consecutive is not consecutive
If u don't wanna mess with any sorting, picking any of three numbers that are consecutive should give you:
- it either is adjacent to both the other numbers (diff1 = 1, diff2 = -1)
- the only number that is adjacent (diff = +-1) should comply the previous statement.
Test for the first condition. If it fails, test for the second one and under success, you've got your secuence; else the set doesn't comply.
Seems right to me. Hope it helps.
I think you need something like the following function (no need of arrays to store data)
<?php
function seqOfthree($entries) {
// entries has to be sorted descending on $e->number
$sequence = 0;
$lastNumber = 0;
foreach($entries as $e) {
if ($sequence==0 or ($e->number==$lastNumber-1)) {
$sequence--;
} else {
$sequence=1;
}
$lastNumber = $e->number;
if ($sequence ==3) {
// if you need the array of sequence you can obtain it easy
// return $records = range($lastNumber,$lastNumber+2);
return true;
}
}
// there isn't a sequence
return false;
}
function isConsecutive($array, $total_consecutive = 3, $consecutive_count = 1, $offset = 0) {
// if you run out of space, e.g. not enough array values left to full fill the required # of consecutive count
if ( $offset + ($total_consecutive - $consecutive_count ) > count($array) ) {
return false;
}
if ( $array[$offset] + 1 == $array[$offset + 1]) {
$consecutive_count+=1;
if ( $consecutive_count == $total_consecutive ) {
return true;
}
return isConsecutive($array, $total_consecutive, $consecutive_count, $offset+=1 );
} else {
return isConsecutive($array, $total_consecutive, 1, $offset+=1 );
}
}
The following function will return the index of the first of the consecutive elements, and false if none exist:
function findConsecutive(array $numbers)
{
for ($i = 0, $max = count($numbers) - 2; $i < $max; ++$i)
if ($numbers[$i] == $numbers[$i + 1] - 1 && $numbers[$i] == $numbers[$i + 2] - 2)
return $i;
return false;
}
Edit: This seemed to cause some confusion. Like strpos(), this function returns the position of the elements if any such exists. The position may be 0, which can evaluate to false. If you just need to see if they exist, then you can replace return $i; with return true;. You can also easily make it return the actual elements if you need to.
Edit 2: Fixed to actually find consecutive numbers.

php: how to add odd/even loop in array

here is my code: http://www.pcgage.net/code.zip (sorry, pasting the code caused it to really mess up, even using the code container).
Scroll to line: 160 (to 174) - this is the loop in question. i want to make it so this is the even part, and then some code to make an odd part, so the loop repeats in this order. The reason is that i want to change the content of this loop alternately.
I am not a coder, so the best thing you could do is to post up the new code and i'll add it in where you tell me too, otherwise i'll get lost :)
Hope that makes sense, if not you can check an earlier post about this issue that explains why i need this (after finding out that css alone cannot solve my problem): css/php: how to solve this div float problem / odd even loop in array
this is the loop:
} elseif ( ( $findpost->ID ) != $id ) {
// all other posts except the current post
$serp_list_li[] = '<div class="serial-contain">
<div class=""><h5>' . $findpost->post_title . '</h5></div>
<div class="text-align">' . $findpost->post_excerpt . ' </div>
<div class="date"> ' . mysql2date('M jS, Y', $findpost->post_date) . ' at ' . mysql2date('g:ia', $findpost->post_date) . '</div>
<div class="comments"><b>' . $findpost->comment_count . ' Comments</b></div>
</div>' . "\n";
}
else {
The three ways are
Modulo
for ($i = 0; $i < 10; $i++)
{
if ($i % 2 == 0)
{
echo "even";
}
else
{
echo "odd";
}
}
Flipping boolean value
$even = true;
for ($i = 0; $i < 10; $i++)
{
if ($even)
{
echo "even";
}
else
{
echo "odd";
}
$even = !$even;
}
And mentioned boolean operator
for ($i = 0; $i < 10; $i++)
{
if ($i & 1 == 0)
{
echo "even";
}
else
{
echo "odd";
}
}
The most fastest is boolean operator. But the most robust is flipping method if you have very different numbers (like running through ID numbers and some are missing).
I haven't looked over the code, but if it's using a variable to count the loop number you can do:
for($i=0;$i<$blah;$i++)
if($i&1){
// ODD
}else{
// EVEN
}
EDIT(1):
I looked at the section you are running into, and now I have another problem, I'm unsure how you are judging what should be odd or not, so I propose two answers:
1: odd loop itteration:
/* Populate the post list array */
// Add here:
$oddLoop = false;
foreach ($findposts as $findpost):
//.....
if($oddLoop=!$oddLoop){
// code for odd loop numbers
}else{
// code for even loop numbers
}
2: Odd ID number:
} elseif ( ( $findpost->ID ) != $id ) {
if($findpost->ID & 1){
// ODD
}else{
//EVEN
}
For loops increment by 1:
$state = 'odd';
for (...)
{
$state = ($state == 'even' ? 'odd' : 'even');
echo $state . PHP_EOL;
}
Output:
even
odd
even
odd
...
If you ever delete an article you could be in trouble - your code assumes that ID runs (odd,even,odd,even) etc.
A better idea would be to create a separate iterator object to feed you the necessary values at each step. Here's what I use:
class LoopingPropertyIterator implements Iterator
{
private $startat = 0, $position = 0;
private $propertylist = array(
'boolean' => array(false, true),
'day' => array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'),
'dow' => array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')
);
public function __construct($args, $startat = 0)
{
$this->startat = (int)$startat;
$this->position = $this->startat;
foreach ($args as $name => $arr)
$this->__set($name, $arr);
}
public function __get($name)
{
if (!array_key_exists($name, $this->propertylist))
throw new Exception(__METHOD__ . " unknown property $name");
$t =& $this->propertylist[$name];
if (is_array($t))
return $t[$this->position % count($t)];
else
return $t;
}
public function __set($name, $arr)
{
$this->propertylist[$name] = $arr;
}
public function current()
{
return $this->position;
}
public function key()
{
return $this->position;
}
public function next()
{
++$this->position;
}
public function rewind()
{
$this->position = $this->startat;
}
public function valid()
{
return true;
}
}
then your output simplifies to
$iter = new LoopingPropertyIterator( array(
'outerclass' => array('serial-contain-right','serial-contain-left'),
'innerclass' => array('text-align2','text-align')
));
...
elseif ( $findpost->ID != $id ) {
$link = get_permalink($firstpost->ID);
$title = $findpost->post_title;
$datetime = mysql2date('M jS, Y', $findpost->post_date).' at '.mysql2date('g:ia', $findpost->post_date);
$serp_list_li[]=
<<<TEXT
<div class="{$iter.outerclass}">
<div class="title">
<h5>{$title}</h5>
</div>
<div class="{$iter->innerclass}">{$findpost->excerpt}</div>
<div class="date">{$date}</div>
<div class="comments">
<a href="{$link}#comments"> title="{$title}">
<b>{$findpost->comment_count} Comments</b>
</a>
</div>
</div>
TEXT;
$iter->next();
}
Are you sure $findpost->ID contains sequential numbers?
You could replace the if/else with s short ternary statement like this:
$side = empty($side) || $side == 'right' ? 'left' : 'right';
$serp_list_li[] = '<div class="serial-contain-' . $side . '">' // ...the rest
This would add a 'left' side first.
Get EvenArray and OddArray
NSArray *numberArray = [NSArray arrayWithObjects:#1,#2,#3,#4,#6,#8,#10, nil];
for (id object in numberArray)
{
if ([object integerValue] % 2 == 0)
{
[evenArray addObject:object];
}
else
{
[oddArray addObject:object];
}
}

Categories