0

The following code works fine with the supplied array.

$arr1 = array(1,2,4,6,7,9,13,15); 

$arr2 = range(1,max($arr1));                                                    

$missing = array_diff($arr2,$arr1); 

foreach ($missing as $key => $val) {
    echo $val;
    echo ",";
}

But if I change $arr1 to contain 001,002,004,006,007,009,013,015, it gives this output: 003,005,008,009,010,012,

I format the output by putting this in the foreach loop:

$val = str_pad($val, 3, "0", STR_PAD_LEFT); 

I cannot figure out why it declares 009 to be missing; why it doesn't declare 011 and 014 to be missing; and why it concludes with a comma.

Is there a way to rewrite the code so it processes the array correctly?

2

2 Answers 2

2

This is because numbers starting with 0 are octal numbers:

http://php.net/manual/pl/language.types.integer.php

To solve this you may store your values in the original array as strings:

$arr = ['001', '002', '005', '011', '007'];

then

echo max($arr); //011

still finds the right one, so now just:

for ($i=1; $i<=ltrim(max($arr), '0'); $i++) {
    $newArr[] = str_pad($i, 3, '0', STR_PAD_LEFT);
}

And then the diff is OK:

print_r(array_diff($newArr, $arr));
Array
(
    [2] => 003
    [3] => 004
    [5] => 006
    [7] => 008
    [8] => 009
    [9] => 010
)

TESTED ON PHP7

Reference:

Sign up to request clarification or add additional context in comments.

1 Comment

I tried using ' ' marks around the values but it didn't work. I'll try that again.
0

Your leading zeroes have made the numbers octal.

6 Comments

Is there a way to handle octals?
Octal, decimal, hexadecimal, etc, are just ways of presenting a number, just the same as binary. We present hexadecimal numbers by putting 0x on the front, and we present octal numbers by putting a zero on the front. So when you have a value 011 in your code you are explicitly declaring a value equivalent to the decimal value 9. Why do you have to put the leading zeroes? If you need that for some tabulated results then I suggest adding leading zeroes to the string output, but leave the input as decimal.
The leading zeroes are coming from the database. They are part of an exam number which has the structure ALPHA-ALPHA-NUMERIC-NUMERIC-NUMERIC-ALPHA-ALPHA
So, for example GC005ABX. Candidates are uniquely identified from 001 - 999; the other information relates to exam centre, level and year. I parse the exam numbers and loop through 001 to 999 and generate correspondence and certificates for each candidate. If a candidate pulls out - say GC035ABX - I want to be able to detect that gap in the sequence and omit them from further actions. Sequencing from 1,2,3 .... 999 won't reference the actual exam numbers in the system.
If you're converting from a string then consider using the intval function (php.net/manual/en/function.intval.php), which takes the base as an optional parameter. The default value is 10, i.e. decimal, but it won't hurt to specify that explicitly.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.