1

This question is sort of carried on from an earlier question of mine here.

However, I would like to illustrate this in the most basic terms, with the hope that someone may be able to help me find a solution to this.

Consider this multidimensional array:

$images = array(
    0 = array(
        'height' => 100
    ),
    1 = array(
        'height' => 90
    ),
    2 = array(
        'height' => 60
    ),
    3 = array(
        'height' => 30
    )
);

Notice that the array is already sorted by height descending!

These images need to be pushed into three columns, whilst trying to keep the height of the columns as even as possible. So the resulting array (of the above example) will look like this:

$gallery_columns = array(
    1 => array(
        'height' => 100
        'images' => array(
            0 = array(
                'height' => 100
            ),
        )
    ),
    2 => array(
        'height' => 90
        'images' => array(
            0 = array(
                'height' => 90
            ),
        )
    ),
    3 => array(
        'height' => 90
        'images' => array(
            0 = array(
                'height' => 60
            ),
            1 = array(
                'height' => 30
            ),
        )
    )
);

I am struggling to write an algorithm to achieve the above. Can anybody see a good way of achieving this without using a lot of nested loops etc?

Community
  • 1
  • 1
Ben Carey
  • 16,540
  • 19
  • 87
  • 169
  • Hey Ben, do you have a certain width that you're looking for? Also, what's the range of the height of the images? :) Happy post-apocalypse! – Josh Brody Jan 02 '13 at 09:25
  • @JoshBrody The width of the images is always the same, and the height of the columns is as tall as it needs to be. It depends on the number of images in the array, the page will have an infinity scroll. See my other question for more details http://stackoverflow.com/questions/13840168/distribute-images-evenly-to-columns-in-gallery – Ben Carey Jan 02 '13 at 09:27

1 Answers1

1

This could be what you are looking for:

$images = array(
    0 => array(
        'height' => 100
    ),
    1 => array(
        'height' => 90
    ),
    2 => array(
        'height' => 60
    ),
    3 => array(
        'height' => 30
    )
);

$gallery_columns = array(
    1 => array(
        'height' => 0,
        'images' => array()
    ),
    2 => array(
        'height' => 0,
        'images' => array()
    ),
    3 => array(
        'height' => 0,
        'images' => array()
    )
);



foreach ($images as $img)
{
    // start with first column as the shortest
    $shortest_colm = &$gallery_columns[1];

    // loop over all the columns, updating the shortest column if shorter
    for ($i = 2; $i <= 3; $i++)
    {
        if ($gallery_columns[$i]['height'] < $shortest_colm['height'])
        {
            $shortest_colm = &$gallery_columns[$i];
        }
    }

    // push the image into the shortest column
    $shortest_colm['height'] += $img['height'];
    $shortest_colm['images'][] = $img;
}

print_r($gallery_columns);

Outputs:

Array
(
    [1] => Array
        (
            [height] => 100
            [images] => Array
                (
                    [0] => Array
                        (
                            [height] => 100
                        )

                )

        )

    [2] => Array
        (
            [height] => 90
            [images] => Array
                (
                    [0] => Array
                        (
                            [height] => 90
                        )

                )

        )

    [3] => Array
        (
            [height] => 90
            [images] => Array
                (
                    [0] => Array
                        (
                            [height] => 60
                        )

                    [1] => Array
                        (
                            [height] => 30
                        )

                )

        )

)

Bonus:

foreach($gallery_columns as &$column)
{
    shuffle($column['images']);
}

Since you are inserting your images in order from largest to smallest, you could shuffle the images once you are done inserting. That way it won't have all the large images at the top, and the small ones at the bottom.

Supericy
  • 5,866
  • 1
  • 21
  • 25
  • Thank you very much, I was going to implement the shuffle function anyway, the problem is, I would like them to always display in the same order. Is there a way to shuffle the order, but ensure it is always the same. I realise that sentence contradicts itself but it you should understand what I mean :-). **The obvious way is to just sort by something like 'date created' but this will mean retrieving the date created from the file, this can be expensive when dealing with a lot of images...** – Ben Carey Jan 02 '13 at 10:03
  • Yes, using [`srand()`](http://php.net/manual/en/function.srand.php). Just make the seed value a constant and assuming you have the same images, they will always be shuffled in the same order. – Supericy Jan 02 '13 at 10:06