Array concatenation troubles

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

User avatar
jayshields
DevNet Resident
Posts: 1912
Joined: Mon Aug 22, 2005 12:11 pm
Location: Leeds/Manchester, England

Array concatenation troubles

Post 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!
User avatar
superdezign
DevNet Master
Posts: 4135
Joined: Sat Jan 20, 2007 11:06 pm

Re: Array concatenation troubles

Post by superdezign »

array_merge() should work fine.

Code: Select all

$a = array_merge($thu, $fav, $other);
User avatar
jayshields
DevNet Resident
Posts: 1912
Joined: Mon Aug 22, 2005 12:11 pm
Location: Leeds/Manchester, England

Re: Array concatenation troubles

Post 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!
User avatar
JayBird
Admin
Posts: 4524
Joined: Wed Aug 13, 2003 7:02 am
Location: York, UK
Contact:

Re: Array concatenation troubles

Post by JayBird »

Nothing to say apart from welcome back! :D
User avatar
pickle
Briney Mod
Posts: 6445
Joined: Mon Jan 19, 2004 6:11 pm
Location: 53.01N x 112.48W
Contact:

Re: Array concatenation troubles

Post by pickle »

Have you tried just adding them together?

Code: Select all

$all = $thu+$fav+$other
Real programmers don't comment their code. If it was hard to write, it should be hard to understand.
User avatar
jayshields
DevNet Resident
Posts: 1912
Joined: Mon Aug 22, 2005 12:11 pm
Location: Leeds/Manchester, England

Re: Array concatenation troubles

Post 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
User avatar
RobertGonzalez
Site Administrator
Posts: 14293
Joined: Tue Sep 09, 2003 6:04 pm
Location: Fremont, CA, USA

Re: Array concatenation troubles

Post 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?
User avatar
jayshields
DevNet Resident
Posts: 1912
Joined: Mon Aug 22, 2005 12:11 pm
Location: Leeds/Manchester, England

Re: Array concatenation troubles

Post 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.
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Re: Array concatenation troubles

Post by Ambush Commander »

I dunno if this will work, but merge to a temporary array ($ret) and then assign $a to that.
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Re: Array concatenation troubles

Post 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);
 
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Re: Array concatenation troubles

Post 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.
User avatar
jayshields
DevNet Resident
Posts: 1912
Joined: Mon Aug 22, 2005 12:11 pm
Location: Leeds/Manchester, England

Re: Array concatenation troubles

Post 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)?
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Re: Array concatenation troubles

Post by Ambush Commander »

ini_set('error_reporting', 1);

Also, make sure there isn't a custom error reporter being registered anywhere (set_error_handler)
User avatar
jayshields
DevNet Resident
Posts: 1912
Joined: Mon Aug 22, 2005 12:11 pm
Location: Leeds/Manchester, England

Re: Array concatenation troubles

Post 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.
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Re: Array concatenation troubles

Post by Ambush Commander »

Hehe, whoops. I gave you the wrong ini setting. :-) Good to hear you fixed it.
Post Reply