Search code examples
phparraysdatasetgroupingtext-parsing

Parse the elements of a flat array and group related data sets


I need to extract the recurring sets of values for Title, Album, and Artist coming from a flat array of strings.

Notice that the file: prefixed element represents the start of a new set of data.

Sample input:

$playlistid = [
    'MPD 0.23.5',
    'file: Blondie/Parallel_Lines/12_Just_Go_Away.flac',
    'Last-Modified: 2016-06-05T17:15:07Z',
    'Format: 44100:16:2',
    'Album: Parallel Lines',
    'AlbumArtist: Blondie',
    'Artist: Blondie',
    'Composer: Debbie Harry',
    'Date: 1978',
    'Genre: Rock',
    'Title: Just Go Away',
    'Track: 12',
    'Time: 214',
    'duration: 213.800',
    'Pos: 0',
    'Id: 745',
    'file: Blondie/Parallel_Lines/13_Once_I_Had_a_Love-aka_The_Disco_Song-1978_version-.flac',
    'Last-Modified: 2016-06-05T17:15:01Z',
    'Format: 44100:16:2',
    'Album: Parallel Lines',
    'AlbumArtist: Blondie',
    'Artist: Blondie',
    'Composer: Chris Stein; Debbie Harry',
    'Date: 1978',
    'Genre: Rock',
    'Title: Once I Had a Love (aka The Disco Song) (1978 version)',
    'Track: 13',
    'Time: 198',
    'duration: 198.000',
    'Pos: 1',
    'Id: 746',
    'file: Blondie/Parallel_Lines/14_Bang_a_Gong-Get_It_On-live-.flac',
    'Last-Modified: 2016-06-05T17:15:03Z',
    'Format: 44100:16:2',
    'Album: Parallel Lines',
    'AlbumArtist: Blondie',
    'Artist: Blondie',
    'Composer: Marc Bolan',
    'Date: 1978',
    'Genre: Rock',
    'Title: Bang a Gong (Get It On) (live)',
    'Track: 14',
    'Time: 330',
    'duration: 330.293',
    'Pos: 2',
    'Id: 747',
    ''
];

I have a foreach loop that searches the above array for the desired fields, and generates three arrays with the desired keys.

foreach($playlistid as $key => $value) {
    if (preg_match('/\bTitle:\s/', $value)) {
        $song_title = $playlistid[$key];
    }
    if (preg_match('/\bArtist:\s/', $value)) {
        $song_artist = $playlistid[$key];
    }
    if (preg_match('/\bAlbum:\s/', $value)) {
        $album_title = $playlistid[$key]
    }
}

The result I'm looking for, is the output to look like this:

Artist, Album, Title

Blondie Parallel Lines Just Go Away
Blondie Parallel Lines Once I Had a Love (aka The Disco Song) (1978 version)
Blondie Parallel Lines Bang a Gong (Get It On) (live)

It's worth bearing in mind that with a various album for example, the Artist and Album tags will also change with each new track.


Solution

    1. Iterate over the payload.
    2. Every time a file label is encountered, create a new reference variable and push it into the result array.
    3. If an Artist, Album, or Title label is encountered, push that value into the reference variable.

    Code: (Demo)

    function parse(array $lines): array
    {
        $result = [];
        foreach ($lines as $line) {
            $split = explode(': ', $line, 2);
            switch ($split[0]) {
                case 'file':
                    unset($ref);
                    $ref = [null, null, null];
                    $result[] = &$ref;
                    break;
                case 'Artist':
                    $ref[0] = $split[1];
                    break;
                case 'Album':
                    $ref[1] = $split[1];
                    break;
                case 'Title':
                    $ref[2] = $split[1];
                    break;
            }
        }
        return $result;
    }
    

    Presenting your data to the end user will be a trivial matter now that the data has been parsed and a multidimensional array has been populated.