Selective alignment of PHP array according to parent keys

I need to flatten an array selectively in PHP, but do it selectively. If the key matches the pattern, then all ancillary items below that key should be included in flat output.

SO If I had a music directory:

=> array of albums => each of which is an array of song titles

Then I could search for a string and get a flat array in the response. So if I were looking for "sun" then I would get the entire catalog for any artist with "sun" on their behalf, plus albums for other artists where "sun" was in the album title.

Hope this makes sense.

Anyone have any thoughts?

0


a source to share


6 answers


Ok, I'm going to assume your data looks like this:

$data = array(
    "Bill Withers" => array (
        "Lovely Day",
        "Use Me",
        "Ain't No Sunshine"
    ),
    "Fleet Foxes" => array (
        "Sun It Rises",
        "White Winter Hymnal"
    ),
    "Billy Joel" => array (
        "Piano Man"
    )
);

      

... and that, given the input "Bill"

you want to get: ["Lovely Day", "Use Me", "Ain't No Sunshine", "Piano Man"]

. Here's one way to do it.



function getSongs($data, $searchTerm) {
    $output = array();
    foreach ($data as $artist => $songs) {
        if (stripos($artist, $searchTerm) !== false)) {
            $output = array_merge($output, $songs);
        }
    }
    return $output;
}

      

... I also assume that you have a good reason not to use a database for this.

+1


a source


Is there a reason you aren't using a database to store what sounds like significant information? It would be pretty easy to write a query in SQL to pull in the data you want.



+3


a source


Do you mean something like that?

$a = array(
    "Sunny" => "Bla-bla1",
    "Sun" => "Bla-bla2",
    "Sunshine" => "Bla-bla3",
);

foreach ($a as $k => $v) 
{
 // check here whenever you want for $k
 // apply something to $v
 if ( ... )
      $b[$i++] = $v;
}

      

0


a source


$sample_data = array(  
    'artist_name' => array(  
        'album_name' => array(  
            'song_name',  
            'other_mp3_id_info'  
            )
        )  
    );

function s2($needle,$haystack) {

    $threads = array();
    foreach ($haystack as $artist_name => $albums) {
        if (stripos($artist_name, $needle) !== false)) {
            $threads[] = $haystack[$artist_name];   //Add all artist albums
        } else {
            foreach ($albums as $album_name => $songs) {
                if (stripos($album_name, $needle) !== false)) {
                    $threads[$artist_name][] = $haystack[$album_name]; //add matching album
                }
            }
        }
    }
    return $threads;
}   

      

0


a source


To compile NickF to work, assuming your data is similar to his, I would write the function this way.

function getSongs($data, $searchTerm) {
    foreach ($data as $artist => $songs) {
        if (stripos($artist, $searchTerm) !== false)) {
            $output[$artist] = $songs;
        }
    }
    return $output or null;
}

      

The results of this function, when no match is found, will explicitly return null instead of an empty array; when multiple matches are found, they will be grouped by their artist. I find a direct purpose $output[$artist] = $songs

to provide more predictable results than array_merge in my own experience. (This also saves the artist to output this data.)

As NickF said, I would assume you have every reason not to do this with a database? The SQL for this would be very simple, for example

SELECT artist, song FROM songs WHERE artist LIKE '%Bill%' GROUP BY artist;

      

0


a source


You can use preg_grep to search, don't forget to clear your input, however:

$matchingArtists = preg_grep('/' . preg_quote($searchString) . '/', array_keys($data));
$matchingSongs = array();
foreach ($data as $artist => $songs) {
    $matchingSongs = array_merge($matchingSongs, preg_grep('/' . preg_quote($searchString) . '/', $songs));
}

      

0


a source







All Articles