php: how to add odd/even loop in array - php

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

Related

PHP if condition: Logical operators for filter from a form

I'm working with a form using the <datalist> tag, I have two input tags getting information from two different arrays. Below the form there is a Kanban board, the objective of the form is to serve as a filter, so when a user fills any of the inputs (or both) the board with fill accordingly.
Here is the problem: I had made two if staments (one for input) that work great when I use them alone but that I don't know how to put together because I don't know how to check which of the inputs has been filled (for that I believe I may have to use the issset() function), then if only one of them is used I need to use the || logical operator between them but if both are filled I need to use the && operator.
Using this condition (|| logical operator):
if (($tasksArray[$i]["responsible-party-names"] == $_POST['members'] && isset($_POST['members'])) ||
(($tasksArray[$i]['project-name'] == $_POST['projects'] && isset($_POST['projects']))))
If I fill only the members input it returns what it should.
If I fill only the projects input it returns all the projects in the array (although when using the if condition without the left part it works well).
Finally, if I fill both inputs I get the right project but all the team members.
What would be the simplest way to get it right?
Update:
This if condition it's inside the moveArray function, what comes after the if block looks like this:
{
$task = '<div id="item'.$i.'"'.'draggable="true" class="c-drag">';
$task .= '<div class="card cardTitle">'.$tasksArray[$i]['content'].'</div>';
$task .= '<div class="card cardDescription">'.$tasksArray[$i]['description'].'</div>';
$task .= '<div class="card cardProjectName">'.$tasksArray[$i]['project-name'].'</div>';
if (isset($tasksArray[$i]["responsible-party-names"])) {
$task .= '<div class="card cardProjectResponsibleName">'.$tasksArray[$i]['responsible-party-names'].'</div>';
} else {
$task .= '<div class="card cardProjectResponsibleName">'."Anyone".'</div>';
}
if ($tasksArray[$i]["due-date"] != "") {
$task .= '<div class="card cardDueDate">'.date("d/m/Y", strtotime($tasksArray[$i]["due-date"])).'</div>';
}
$task .= '</div>';
return $task;
}
Then I call the function on every part of the board (unassigned, to do, in progress, finished)
echo '<div id="board">';
echo '<div id="unassing">';
echo '<div id="unassing-bg" class="title">Unassigned</div>';
for ($i=0; $i < $tasksLenght; $i++) {
if (isset($tasksArray[$i]['boardColumn']) === false) {
echo(moveArray($i, $tasksArray));
}
}
echo '</div>';
echo '<div id="todo">';
echo '<div id="todo-bg" class="title">To Do</div>';
for ($i=0; $i < $tasksLenght; $i++) {
if (isset($tasksArray[$i]['boardColumn']) && $tasksArray[$i]['boardColumn']['id'] == "9805") {
echo(moveArray($i, $tasksArray));
}
}
echo '</div>';
echo '</div>';
And that produce sort of "a card" with data about a task in the corresponding place of the board.
You actually need the isset to come before trying to access the key on $_POST to prevent the "undefined" error.
I am assuming you have some code that looks like this:
$matchingTasks = [];
for ($i=0; $i <= count($tasksArray); $i++) {
...
}
return $matchingTasks; // or something
If that is the case, what you want is more like this:
matchingTasks = [];
foreach ($tasksArray as $task) {
// Store your search values
$members = isset($_POST['members']) ? $_POST['members'] : false;
$projects = isset($_POST['projects']) ? $_POST['projects'] : false;
// Store the search matches, only if you are searching by that key
$members_match = $members && $task["responsible-party-names"] == $members;
$projects_match = $projects && $task['project-name'] == $projects;
// if you are searching for BOTH must match BOTH
if ($members && $projects)
if ($members_match && $projects_match) {
$matchingTasks[] = $task;
}
continue;
}
// if you are searching for EITHER can match EITHER
if ($members XOR $projects) {
if ($members_match || $projects_match) {
$matchingTasks[] = $task;
}
continue;
}
// if you are not searching match ALL
$matchingTasks[] = $task;
}
return $matchingTasks;
More advanced, and would allow for more customization, is to stack these in a filter pattern like this:
$members = isset($_POST['members']) ? $_POST['members'] : false;
$projects = isset($_POST['projects']) ? $_POST['projects'] : false;
if ($members)
$tasksArray = filter_by_members($tasksArray, $members);
if ($projects)
$tasksArray = filter_by_project($tasksArray, $projects);
return $tasksArray;
//... elsewhere
function filter_by_members($tasks, $members) {
$result = [];
foreach ($tasks as $t) {
if ($task["responsible-party-names"] == $members) {
$result[] = $task;
}
}
return $tasks;
}
function filter_by_project($tasks, $project) {
$result = [];
foreach ($tasks as $t) {
if ($task["project-name"] == $project) {
$result[] = $task;
}
}
return $tasks;
}
This would let you stack new search filters, like filter_by_id or filter_by_date and by defining filter functions you can stack as many as you like without getting crazy with the logic.

Show next and previous keys of an array with cycling

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);

Finding all points contouring the overlapping squares

The setup:
a. 2D surface
b. points (with x, y coordinates) which when connected form squares.
c. I found an algorithm that finds the intersection points of those squares so assume we have them as well.
The question is: how do I get points that contour the squares.
I've included an image for better understanding.
I was looking into http://en.wikipedia.org/wiki/Convex_hull_algorithms but it seems like they all skip those intersections (the 90' angles).
I am writing this in php but i'd love to even see a pseudo code if at all possible.
<?php
//WARNING! we assume coords as non-polar. for this to work on large-scale, you need to convert polar into decard coords.
//Can be done outside this script.
//Points sample:
$points_raw=json_decode('{"1":[[41.014357690351,-73.73715475406],[41.029170309649,-73.73715475406],[41.014357690351,-73.75644124594],[41.029178309649,-73.73721675406],[41.014365690351,-73.75650324594],[41.031554690351,-73.73806375406],[41.046091309649,-73.78489424594],[41.014688690351,-73.78819424594],[41.012691690351,-73.75993275406],[41.012691690351,-73.77921924594],[41.015809690351,-73.75893475406],[41.053689309649,-73.76006575406],[41.053689309649,-73.77935224594],[41.050793309649,-73.78376624594],[41.043862309649,-73.79638424594],[41.029049690351,-73.79638424594],[41.019350690351,-73.79608224594],[41.033268690351,-73.73637875406],[41.048081309649,-73.73637875406],[41.048081309649,-73.75566524594],[41.014365690351,-73.75644124594],[41.029170309649,-73.73721675406],[41.018165690351,-73.75650324594],[41.029178309649,-73.74662775406],[41.031554690351,-73.74662775406],[41.033268690351,-73.73806375406],[41.043862309649,-73.78489424594],[41.019350690351,-73.78819424594],[41.015809690351,-73.75993275406],[41.014688690351,-73.77921924594],[41.018165690351,-73.75893475406],[41.047266309649,-73.76006575406],[41.050793309649,-73.77935224594],[41.046091309649,-73.78376624594],[41.029049690351,-73.79608224594],[41.047266309649,-73.75566524594]]}',1);
//BEGIN HERE:
$points=$points_raw[1];
function to_round($val)
{
//here we can try conversion from polar to decard. not sure if will work
//no conversion for now, but just rounding for comparsion
return round($val*1000000000000);
}
function sort_points_array($a, $b, $which)
{
$da=to_round($a[$which]);
$db=to_round($b[$which]);
if ($da == $db) {
return 0;
}
return ($da < $db) ? -1 : 1;
}
function sort_by_0($a, $b)
{
return sort_points_array($a, $b, 0);
}
function sort_by_1($a, $b)
{
return sort_points_array($a, $b, 1);
}
//BEGIN OF UNOPTIMIZED SORT
//sort by columns from left to right (does not have to be left/right on the map)
//but we will try :) 0 -> Y, 1 -> X
//sort by X, so lower X will be on top of array.
//and each point in those columns will be also sorted from top to bottom by their Y
usort($points,"sort_by_1");
//then foreach to split array by "columns";
$column_counter=0;
$point_columns=array();
$point_columns[$column_counter][]=$points[0];
foreach($points as $n_point=>$p_coords)
{
if($n_point>0)
{
if(to_round($p_coords[1]) > to_round($point_columns[$column_counter][1][1]))
$column_counter++;
$point_columns[$column_counter][]=$p_coords;
}
}
//now sort each column
$sorted_point_columns=array();
foreach($point_columns as $pcn => $p_column)
{
usort($p_column,"sort_by_0");
$sorted_point_columns[$pcn]=$p_column;
}
//SAME TO MAKE sorted_point_rows
usort($points,"sort_by_0");
$row_counter=0;
$point_rows=array();
$point_rows[$row_counter][]=$points[0];
foreach($points as $n_point=>$p_coords)
{
if($n_point>0)
{
if(to_round($p_coords[0]) > to_round($point_rows[$row_counter][0][0]))
$row_counter++;
$point_rows[$row_counter][]=$p_coords;
}
}
$sorted_point_rows=array();
foreach($point_rows as $prn => $p_row)
{
usort($p_row,"sort_by_1");
$sorted_point_rows[$prn]=$p_row;
}
// END OF UNOPTIMIZED SORT
//output array
$final_points_poly=array();
//clearly first point will be from 1st row;
//and we will go to the RIGHT in current row to find next point
$final_points_poly[0]=$sorted_point_rows[0][0];
//and let the magic begin:
$finished=false;
$last_point_index=0;
$points_total=count($points);
$pos_x=0; //pos by columns
$pos_y=0; //pos by rows
$relative_X=0; //relative X position in current ROW;
$relative_Y=0; //relative Y position in current COLUMN;
$rule=1; // right / down = 1, left / up = -1
//detect if we go by X or Y
$going_Y=false;
$finished=false;
while(!$finished)
{
if($going_Y)
{
$relative_Y+=$rule;
$last_point_index+=1;
$cur_p=$sorted_point_columns[$pos_x][$relative_Y];
$final_points_poly[$last_point_index]=$cur_p;
$going_Y = !$going_Y;
//search for pos_y:
foreach($sorted_point_rows as $cur_y => $row)
{
if(to_round($row[0][0]) == to_round($cur_p[0]))
{
$pos_y=$cur_y;
//search for relative_X
foreach($row as $cur_rel_x => $check_point)
{
if(to_round($check_point[1]) == to_round($cur_p[1]))
{
$relative_X=$cur_rel_x;
$rule = ($relative_X % 2 == 0 ? 1 : -1);
break 2;
}
//error_check 1
if($cur_rel_x == count($row)-1)
echo "error with calculating relative_X! check your data!\n";
}
}
//error_check 2
if($cur_y == count($sorted_point_rows)-1)
echo "error with calculating pos_y! check your data!\n";
}
}
else
{
$relative_X+=$rule;
$last_point_index+=1;
$cur_p=$sorted_point_rows[$pos_y][$relative_X];
$final_points_poly[$last_point_index]=$cur_p;
$going_Y = !$going_Y;
//search for pos_x:
foreach($sorted_point_columns as $cur_x => $column)
{
if(to_round($column[0][1]) == to_round($cur_p[1]))
{
$pos_x=$cur_x;
//search for relative_Y
foreach($column as $cur_rel_y => $check_point)
{
if(to_round($check_point[0]) == to_round($cur_p[0]))
{
$relative_Y=$cur_rel_y;
$rule = ($relative_Y % 2 == 0 ? 1 : -1);
break 2;
}
//error_check 1
if($cur_rel_y == count($column)-1)
echo "error with calculating relative_Y! check your data!\n";
}
}
//error_check 2
if($cur_x == count($sorted_point_columns)-1)
echo "error with calculating pos_x! check your data!\n";
}
}
if($last_point_index == $points_total-1)
{
$finished=true;
}
}
echo "all points:\n";
print_r($final_points_poly);
/*
//generate markers for google mapping
$out = "var bbs=[];var markers=[];";
$out .= "var pinI = new google.maps.MarkerImage('http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|ADDE63');";
$out .= "var pinI2 = new google.maps.MarkerImage('http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|FF8C00');";
$out .= "var pinI3 = new google.maps.MarkerImage('http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|990099');";
$out .= "bbs.push(new google.maps.Polyline({ ";
$out .= "path: [";
foreach($final_points_poly as $m){
$out .= "new google.maps.LatLng(".join(",",$m)."),";
}
$out .= "],";
$out .= "strokeColor: 'black', strokeOpacity: 0.4, strokeWeight: 1 }));";
$f = fopen("bbs.js",'w');
fwrite($f,$out);
fclose($f);
*/
?>

if else simple beginner issue

Good day guys,
I've made a sweet favorites function with php mysql and ajax, and its working great. Now I want to show 'favorite' when favorite = 0 and show 'unfavorite' when favorite = 1
if ($favorites == 0) {
$favorite = 'Favorite';
}
if ($favorites == 1) {
$unfavorite = 'unFavorite';
}
and echo it in the row as :
<div id="favorites">' .($favorite). ' ' .($unfavorite). '</div>
The problem is: when favorite = 0, both $favorite and $unfavorite are being shown. When favorite = 1 only $unfavorite is being shown correctly. Of course it should be $favorite OR $unfavorite. I assume the problem is clear and simple to you, please assist :)
Thanks in advance
It's easier to use just one variable:
$text = ''
if ($favorites == 0) {
$text = 'Favorite';
} else {
$text = 'unFavorite';
}
...
echo $text;
If you want to check $favorite, you are using the wrong variable in your control statement. Also, it is better coding practice to use elseif rather than if for that second if. One more thing: it's easier to manage one resulting variable.
$output = "";
if ($favorite == 0) {
$output = 'Favorite';
}
elseif ($favorite == 1) {
$output = 'unFavorite';
}
...
echo $output; // Or whatever you want to do with your output
Is $favorites an integer?
Anyway try using three equal signs (===) or else instead of the second if:
if ( $favorites === 0 )
{
// ...
}
else // or if ($favorites === 1)
{
// ...
}
You're making a toggle, so you only need one variable:
if(empty($favourites)){
$fav_toggle = 'Favorite';
} else {
$fav_toggle = 'unFavorite';
}
echo $fav_toggle;
Same code is working on me if I assigned $favorites = 0; or $favorites = 1;
You can also use if else
$favorites = 1;
if ($favorites == 0) {
$favorite = 'Favorite';
}
else if ($favorites == 1) {
$unfavorite = 'unFavorite';
}

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.

Categories