tags:

views:

100

answers:

5

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
                        }
                    }
+1  A: 

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.

zebediah49
A: 

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
Kris
A: 

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;
}
Eineki
Hi Eineki, the entries are in descending order, how would you modify your code to suit that?
pauld78
@pauld78 just revert the + signs into - ones (I've already modified the function to do that)
Eineki
A: 

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.

Daniel Egeberg
I believe this fails for `findConsecutive(array(1,5,9123));`.
Frank Farmer
@Frank Farmer how does it fail? It returns int(0), which is the index of the first element of the consecutive three. Note that 0 !== false.
Daniel Egeberg
1 5 and 9123 are not consecutive.
Frank Farmer
Duh... yes, of course you're right. Fixed now. Thanks.
Daniel Egeberg
A: 

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.

misterte