Multidimensional array: implode both outer and inner arrays‏

Using this sample multidimensional array (of a palette which contains colours, which in turn contains their respective shades), let’s say I would like to display the colours in an imploded list (comma-separated) and, if applicable, its respective shades in brackets, also in an imploded (comma-separated) list.

I can easily implode the inner array (shades), but cannot figure out how to do that with the outer array (colours) given it contains the array of shades which must be run through for each colour.

I’ve seen there are several solutions for imploding a multidimensional array, but these seem to be without requiring running through a possible inner array for each. Perhaps there is another method by which to separate the entries with a comma?

And while I’m on the subject, is there a way of replacing the last comma of an imploded string with ‘and’?

Thanks in advance.

		$sql = "SELECT DISTINCT colour_id, colour_nm, colour_url
				FROM palettecolours
				INNER JOIN colour ON colourid = colour_id
				WHERE paletteid = '$palette_id'";
		while ($row = mysqli_fetch_array($result))
		{
			$colour = '<a href = "/colour/' . $row['colour_name'] . '">' . $row['colour_url'] . '</a>';
			$colours[$row['colour_id']] = array('colour' => $colour, 'shades' => array());
		}

		$sql = "SELECT colourid, shade_name, shade_url
				FROM palettecolours
				INNER JOIN shade ON shadeid = shade_id
				WHERE paletteid = '$palette_id'";
		while ($row = mysqli_fetch_array($result))
		{
			$shade = '<a href = "/shade/' . $row['shade_name'] . '">' . $row['shade_url'] . '</a>';
			$colours[$row['colourid']]['shades'][] = array('shade' => $shade);
		}
		<?php foreach ($colours as $colour): ?>
		<?php echo $colour['colour']; ?>
		<?php if(!empty($colour['shades'])) { ?>(<?php echo implode(", ", $colour['shades']); ?>)<?php } ?>
		<?php endforeach; ?>

[INDENT]CURRENT DISPLAY:-
Red (Magenta, Burgundy, Crimson) Blue Green Yellow (Egyptian Cotton, Magnolia) White (Soft Moon)

DESIRED OUTCOME:-
Red (Magenta, Burgundy, Crimson), Blue, Green, Yellow (Egyptian Cotton, Magnolia), White (Soft Moon)[/INDENT]

Not tested, but this should work

        <?php foreach ($colours as $colour): ?>
        <?php echo $colour['colour']; ?>
        <?php if(!empty($colour['shades'])) { ?>(<?php echo implode(", ", $colour['shades']); ?>)<?php } ?>
        <?php echo ", "; ?>
        <?php endforeach; ?>

Thanks Mittineague.

Sorry, but that would add an unwanted comma to the end of the string:-

Red (Magenta, Burgundy, Crimson), Blue, Green, Yellow (Egyptian Cotton, Magnolia), White (Soft Moon),

I think the easiest way would be to put a string together instead of all the echoes. eg.

<?php
$output_str = "";
foreach ($colours as $colour):
       $output_str .= $colour['colour'];
       if(!empty($colour['shades'])) {
               $output_str .= "(" . implode(", ", $colour['shades']) . ")";
       }
       $output_str .=  ", ";
endforeach;
echo $output_str;
?>

you could then [fphp]trim/fphp the last comma or replace with “and” before output.

Ah, nice - thanks! I thought I’d have to use some form of array mapping and implosion but this is much simpler.

The final output uses the rtrim function…

echo rtrim($output_str, ', ');

…which gives me:-

Red (Magenta, Burgundy, Crimson), Blue, Green, Yellow (Egyptian Cotton, Magnolia), White (Soft Moon)

I if want to change the comma that precedes ‘White’ then I can use some regex but reckon I’m okay from here on in.

Thanks again!

Great you got it!

I don’t know if you would need regex. Adding a [fphp]strrpos[/fphp] and a [fphp]str_replace[/fphp] in the loop might be better.

Another option, without any regex or something similar:


 $colours = array(array('colour' => 'Red' ,'shades' => array('Magenta', 'Burgundy', 'Crimson')), array('colour' => 'Blue'), array('colour' => 'Green'), array('colour' => 'Yellow', 'shades' =>  array('Egyptian Cotton', 'Magnolia')), array('colour' => 'White', 'shades' => array('Soft Moon')));

$res = array();
foreach ($colours as $colour) {
       $tmp = $colour['colour'];
       if (!empty($colour['shades'])) {
               $tmp .= " (" . implode(", ", $colour['shades']) . ")";
       }
       $res[] = $tmp;
}
echo implode(', ', array_slice($res, 0, -1)).' and '.$res[count($res) -1];
// OUTPUT: Red (Magenta, Burgundy, Crimson), Blue, Green, Yellow (Egyptian Cotton, Magnolia) and White (Soft Moon)

Cheers.

Another method a friend has suggested it checking if it’s the last iteration (http://stackoverflow.com/questions/1070244/how-to-determine-the-first-and-last-iteration-in-a-foreach-loop) and echoing the comma for all iterations except the last one. This also allows me to change the penultimate comma to an ‘and’ as well.

Don’t know how I didn’t think of that one before!

The most simple approach is nested implodes, as Scallio was going for.

Also, this:

            $colours[$row['colourid']]['shades'][] = array('shade' => $shade); 

That last array is really unnecessary.

            $colours[$row['colourid']]['shades'][] = $shade; 

You know everything in the ‘shades’ numerical array is a shade. Dont really need an extra dimension for labelling it a shade again.

Ah, yes. Had realised after posting and had since remedied in my code, but thanks for pointing out.