Page 1 of 2

Array concatenation troubles

Posted: Fri Jun 13, 2008 7:31 am
by jayshields
First off, I'd like to say a big hello to everyone again, as this is my first post in a long time.

Now, to the point...

I've got a directory full of images, if the file name starts with "f!" then it's a thumbnail (and favourite), it it starts with "f" then it's just a favourite. Any other starting character(s) and it's just a normal image.

I want to output all these images, but I want the thumbnails (f!) to come out first, then the favourites, then the others. Also, I want each type of image(thumbs, faves and others) to be sorted by modification date seperately.

I couldn't even get usort to work with my own compare function when disregarding the date modification sorting (so the file names were just in a plain old array), so I quickly moved away from that method.

When I realised I needed date modification sorting too, I got all the filenames and dates in an associative array (filenames as keys, dates as values).

So I set about creating my own function to sort this associative array. The logical way to go about it was splitting the array into three 3 subparts, sorting them by date modified, and then concatenating them. After alot of messing around with array_push, and array_merge, I realised you can't actually concatenate arrays easily.

This is what I ended up with - it works, but surely it's not the best way to accomplish something like this?

Code: Select all

 
function imageSort(&$a)
{
    //loop through each image
    foreach($a as $k => $v)
    {
        //build the 3 sub parts
        if(substr($k, 0, 2) == "f!")
            $thu[$k] = $v;
        else if($k{0} == "f")
            $fav[$k] = $v;
        else
            $other[$k] = $v;
    }
 
    //sort the 3 subparts
    asort($thu);
    asort($fav);
    asort($other);
 
    //concatenate the arrays
    foreach($fav as $k => $v)
        $thu[$k] = $v;
 
    foreach($other as $k => $v)
        $thu[$k] = $v;
 
    $a = $thu;
}
If no one can improve upon this, then atleast it will be here for anyone else with array concatenation problems!

Re: Array concatenation troubles

Posted: Fri Jun 13, 2008 7:51 am
by superdezign
array_merge() should work fine.

Code: Select all

$a = array_merge($thu, $fav, $other);

Re: Array concatenation troubles

Posted: Fri Jun 13, 2008 8:33 am
by jayshields
After a quick test, it seems that it does work, but it still doesn't work with my actual data. If I replace the bottom two foreach loops in my function with

Code: Select all

array_merge($thu, $fav, $other);
then it only outputs the contents of the $thu array.

After some more testing, it seems that it's my function is screwing things up, because array_merge works with my test data directly.

Edit: It's because I didn't grab the return value or array_merge() - d'oh!

Re: Array concatenation troubles

Posted: Fri Jun 13, 2008 9:15 am
by JayBird
Nothing to say apart from welcome back! :D

Re: Array concatenation troubles

Posted: Fri Jun 13, 2008 9:49 am
by pickle
Have you tried just adding them together?

Code: Select all

$all = $thu+$fav+$other

Re: Array concatenation troubles

Posted: Fri Jun 13, 2008 1:02 pm
by jayshields
Well that seems to produce no results in my function but works when I test it seperately.

To illustrate

Code: Select all

<?php
    $a = array("f!163-500.jpg" => "1213282462", "f!paint jobs 26807 007-500.jpg" => "1209910554");
    $g = array();
    $h = array("paint jobs 26807 001-500.jpg" => "1209910539", "163-500.jpg" => "1213283088", "164-500.jpg" => "1213282435");
 
    print_r($a + $g + $h);
    print_r(array_merge($a, $g, $h));
 
?>
outputs two (correct in my case) identical results.

But my function will only output the correct result when it's like this:

Code: Select all

function imageSort(&$a)
{
    //loop through each image
    foreach($a as $k => $v)
    {
        //build the 3 sub parts
        if(substr($k, 0, 2) == "f!")
            $thu[$k] = $v;
        else if($k{0} == "f")
            $fav[$k] = $v;
        else
            $other[$k] = $v;
    }
 
    //sort the 3 subparts in reverse order
    arsort($thu);
    arsort($fav);
    arsort($other);
 
    //concatenate the arrays
    foreach($fav as $k => $v)
        $thu[$k] = $v;
 
    foreach($other as $k => $v)
        $thu[$k] = $v;
 
    $a = $thu;
 
    //$a = $thu + $fav + $other;
 
    //$a = array_merge($thu, $fav, $other);
}
If I comment out the last 2 foreach loops and $a = $thu; then uncomment either of the other 2 lines it produces incorrect results.

I guess it's to do with something else in my function, but I can't figure out what without removing things bit by bit because it always works fine concatenating the arrays using the 2 foreach loops.

I found this via Google which leads me to believe it's more hassle than it's worth trying to get a more efficient way of doing this http://www.faqts.com/knowledge_base/view.phtml/aid/343

Re: Array concatenation troubles

Posted: Fri Jun 13, 2008 1:14 pm
by RobertGonzalez
You are pulling these files all from one directory right? Why not build your arrays using a glob() call for each file name type then do what you will with each array?

Re: Array concatenation troubles

Posted: Sun Jun 15, 2008 12:40 pm
by jayshields
Grabbing the filenames/dat mod times is done seperately, this function concentrates on sorting the filenames/date modification times only. Anyway, that has nothing to do with it. It's something to do with the splitting of the array that is making my function go wrong when using the other methods, but I don't have time to test it thoroughly when I already have a working method anyway. I was just hoping that someone could point out an easy mistake I looked over.

Re: Array concatenation troubles

Posted: Sun Jun 15, 2008 4:39 pm
by Ambush Commander
I dunno if this will work, but merge to a temporary array ($ret) and then assign $a to that.

Re: Array concatenation troubles

Posted: Sun Jun 15, 2008 4:54 pm
by Ambush Commander
Actually, I just tested it and things seem to be hunky dory. What are you running?

Code: Select all

<?php
 
function imageSort(&$a)
{
    
    $thu = array();
    $fav = array();
    $other = array();
    
    //loop through each image
    foreach($a as $k => $v)
    {
        //build the 3 sub parts
        if(substr($k, 0, 2) == "f!")
            $thu[$k] = $v;
        else if($k{0} == "f")
            $fav[$k] = $v;
        else
            $other[$k] = $v;
    }
 
    //sort the 3 subparts in reverse order
    arsort($thu);
    arsort($fav);
    arsort($other);
 
    //concatenate the arrays
    //foreach($fav as $k => $v)
    //    $thu[$k] = $v;
 
    //foreach($other as $k => $v)
    //    $thu[$k] = $v;
 
    //$a = $thu;
 
    //$a = $thu + $fav + $other;
 
    $a = array_merge($thu, $fav, $other);
}
 
function shuffle_with_keys(&$array) {
    /* Auxiliary array to hold the new order */
    $aux = array();
    /* We work with an array of the keys */
    $keys = array_keys($array);
    /* We shuffle the keys */
    shuffle($keys);
    /* We iterate thru' the new order of the keys */
    foreach($keys as $key) {
      /* We insert the key, value pair in its new order */
      $aux[$key] = $array[$key];
      /* We remove the element from the old array to save memory */
      unset($array[$key]);
    }
    /* The auxiliary array with the new order overwrites the old variable */
    $array = $aux;
  }
 
$a = array("f!163-500.jpg" => "1213282462", "f!paint jobs 26807 007-500.jpg" => "1209910554");
$g = array('fasdf.jpg' => '1213282462');
$h = array("163-500.jpg" => "1213283088", "164-500.jpg" => "1213282435", "paint jobs 26807 001-500.jpg" => "1209910539");
 
$b = $a + $g + $h;
var_dump($b);
 
shuffle_with_keys($b);
 
var_dump($b);
 
imageSort($b);
 
var_dump($b);
 

Re: Array concatenation troubles

Posted: Sun Jun 15, 2008 4:55 pm
by Ambush Commander
Oh duh. You need to initialize your $thu, $fav and $other arrays before writing to them. PHP won't complain if you write to a non-existent array's index, but it will complain if you try to array merge a null. Turn on errors please.

Re: Array concatenation troubles

Posted: Sun Jun 15, 2008 6:14 pm
by jayshields
That's it! Sorted.

Sorry about the errors - I would/should have caught that myself. As I mentioned earlier, I haven't used PHP in a long time!

I have actually got

Code: Select all

error_reporting(E_ALL);
at the top of my config file, which is included everywhere, and I noticed error reporting was non-existant straight away, but managed to do OK without it (until now...).

Is this something to do with my version (5.2.5) of PHP? Because this is much newer than what I used to work with, when this method would always be fine. Or have I missed something when setting up Apache (2.2.8)?

Re: Array concatenation troubles

Posted: Sun Jun 15, 2008 6:36 pm
by Ambush Commander
ini_set('error_reporting', 1);

Also, make sure there isn't a custom error reporter being registered anywhere (set_error_handler)

Re: Array concatenation troubles

Posted: Sun Jun 15, 2008 6:48 pm
by jayshields
Hmm, set_error_reporting isn't anywhere and changing error_reporting(E_ALL) to ini_set('error_reporting', 1) doesn't make a difference.

Just checked php_info() and it turns out display_errors was set to Off instead of On, so that's fixed it. I really can't remember changing that and I can't think of why I would, and it can't of come like that!

Anyway, thanks for the help.

Re: Array concatenation troubles

Posted: Sun Jun 15, 2008 7:09 pm
by Ambush Commander
Hehe, whoops. I gave you the wrong ini setting. :-) Good to hear you fixed it.