4

I'd like to check an array of image filenames to see how many consecutive images have the same orientation using PHP.

In the following example, I'd like to know that indexes 1 through 4 have the same orientation OR that there are four consecutive images with the same orientation at the first index.

For reference, "orientation" values are "V" for vertical and "H" for horizontal.

e.g.,

Array
(
[0] => Array
    (
        [filename] => image0.jpg
        [orientation] => V
    )

[1] => Array
    (
        [filename] => image1.jpg
        [orientation] => H
    )

[2] => Array
    (
        [filename] => image2.jpg
        [orientation] => H
    )

[3] => Array
    (
        [filename] => image3.jpg
        [orientation] => H
    )

[4] => Array
    (
        [filename] => image4.jpg
        [orientation] => H
    )
[5] => Array
    (
        [filename] => image5.jpg
        [orientation] => V
    )
[...]
[n]
}

There has to be a better way than

if ([i]['orientation'] == [i+1]['orientation'])
if ([i]['orientation'] == [i+1]['orientation'] == [i+2]['orientation'])
if ([i]['orientation'] == [i+1]['orientation'] == [i+2]['orientation']  == [i+3]['orientation'])
if ([i]['orientation'] == [i+1]['orientation'] == [i+2]['orientation'] == [i+3]['orientation'] == [i+4]['orientation'])
2

1 Answer 1

7

If I understand the logic you're trying to apply, SplQueue provides all the functionality to solve your problem thoroughly and tidily OOP fashion.

I wrote this up and it tests out fine for me based on the use case you provided.

// your data array
$array = array(
    array("filename"=>"image0.jpg","orientation"=>"V"),
    array("filename"=>"image1.jpg","orientation"=>"H"),
    array("filename"=>"image2.jpg","orientation"=>"H"),
    array("filename"=>"image3.jpg","orientation"=>"H"),
    array("filename"=>"image4.jpg","orientation"=>"H"));


function queue($array) {

    // grab a new SqlQueue object -- http://php.net/manual/en/class.splqueue.php    
    $q = new SplQueue;
    foreach($array as $key=>$val) {
        // if this is the first iteration or the queue object was emptied out
        if ($q->isEmpty()) {
            $q->enqueue($val);
        } else {

            if ($val['orientation'] == $array[$key--]['orientation']) {
                $q->enqueue($val);
                if (($q->count() % 4) == 0) {
                    return $q;
                }
            } else {
                // Dequeue the whole group on interrupt
                while ($q->valid()) {
                   $q->dequeue();
                }
                // ... and start filling the queue, the mismatch as the new pattern
                $q->enqueue($val);
            }
        }
    }
}

$q = queue($array);
echo $q->count();

The data property enqueued() sets is private, so you'll have to make it visibile in your class.

If you're using PHP 5.4+, you can replace that decremented array index call with function array dereferencing, like so:

    if ($val['orientation'] == prev($array[$key])['orientation'] {
    //...

Everything else is pretty standard. The modulus test returns the queue object as soon as it acquires 4 matches in a row, since SplQueue objects enforce sequenced indexed FIFO, and can't be unsequenced. Finally, if matching interrupts before the queue has 4 matches in a row, Spl's Iterators make emptying the queue to start over - beginning with the mismatch (first new pattern.)

That should cover everything...

HTH :)

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

6 Comments

For some reason, I thought you wanted to enforce a hard limit on the number of matches - ie, 4. Hopefully this is enough to get you going and you can see how small modification would allow you to gather matches until mismatch and acquire the total number, or a queue of all the matched objects, etc. ^_^
Not quite what I'm looking for, but may be useful nonetheless.
What exactly did you have in mind? I wasn't quite sure what your context was, but a function wrapping the desired behavior is pretty universal - especially since the desired behavior (as I understood it anyway) - there's no single function that does what you want, but a it is certainly possible to chew on it with array- and string-handling functions to achieve the same outcome. Messy and awkward, definitely not one line - but possible. Were you focusing on comparison / control while iterating through multi-dimensional arrays?
The ultimate goal is to output lines of images that have the same orientations. For example, first line has all vertical images and then there is a break when the first horizontal image is found. Then the second line has all horizontal images until a vertical image is found. Then the third line has all vertical images until a horizontal image is found and so on... Wondering if I could simply use some kind of while loop.
Is there a max number of images per line? I caught that it was for UI - like, continual scroll or... ? I will edit and post in a second.
|

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.