开发者

Group duplicate array keys in a multidimensional array into subarray

I have a multidimensional array called $songs, which outputs the following:

Array
(
    [0] => Array
        (
            [Michael Jackson] => Thriller
        )

    [1] => Array
        (
            [Michael Jackson] => Rock With You
        )

    [2] => Array
        (
            [Teddy Pendergrass] => Love TKO
        )

    [3] => Array
        (
            [A开发者_开发知识库CDC] => Back in Black
        )
)

I would like to merge the arrays which have duplicate keys, so I can get the following:

Array
(
    [0] => Array
        (
            [Michael Jackson] => Array
            (
                [0] => Thriller
                [1] => Rock With You
            )
        )

    [1] => Array
        (
            [Teddy Pendergrass] => Love TKO
        )

    [2] => Array
        (
            [ACDC] => Back in Black
        )
)

How do I do this?

Bonus points for giving me the code to output the array like:

<h2>Michael Jackson</h2>
<ul>
    <li>Thriller</li>
    <li>Rock With You</li>
</ul>

<h2>Teddy Pendergrass</h2>
<ul>
    <li>Love TKO</li>
</ul>

<h2>ACDC</h2>
<ul>
    <li>Back in Black</li>
</ul>


This should do it, it's not exactly what you want but I don't see a reason why you'd need to index the resulting array numerically, and then by artist.

$source = array(
    array('Michael Jackson' => 'Thriller'),
    array('Michael Jackson' => 'Rock With You'),
    array('Teddy Pendergrass' => 'Love TKO'),
    array( 'ACDC' => 'Back in Black')
);

$result = array();

foreach($source as $item) {
    $artist = key($item);
    $album = current($item);

    if(!isset($result[$artist])) {
        $result[$artist] = array();
    }
    $result[$artist][] = $album;
}

And you can loop the $result array and build your HTML like this:

foreach($result as $artist => $albums) {
    echo '<h2>'.$artist.'</h2>';
    echo '<ul>';
    foreach($albums as $album) {
        echo '<li>'.$album.'</li>';
    }
    echo '</ul>';
}

Which would result in a similar list that you described.


The native PHP function array_merge_recursive() will cut 9 lines of code down to 1 thanks to the splat operator.

Code: (Demo)

$result = array_merge_recursive(...$songs);

Output:

array (
  'Michael Jackson' => 
  array (
    0 => 'Thriller',
    1 => 'Rock With You',
  ),
  'Teddy Pendergrass' => 'Love TKO',
  'ACDC' => 'Back in Black',
)

This does not create your desired array structure; it creates the most compact version of your associative data.

When it comes to printing your data, I recommend using an html template string and feeding data into its placeholders.

Because the grouped $songs data may be scalar or iterable (by consequence of array_merge_recursive()), that variable must be explicitly cast as array type data before feeding it into implode().

$template = <<<HTML
<h2>%s</h2>
<ul>
    <li>%s</li>
</ul>

HTML;

foreach ($result as $artist => $songs) {
    printf(
        $template,
        $artist,
        implode('</li><li>', (array)$songs)
    );
}

Output:

<h2>Michael Jackson</h2>
<ul>
    <li>Thriller</li><li>Rock With You</li>
</ul>
<h2>Teddy Pendergrass</h2>
<ul>
    <li>Love TKO</li>
</ul>
<h2>ACDC</h2>
<ul>
    <li>Back in Black</li>
</ul>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜