I have to find where a given string is in my multidimensional array. So this is my array
$input = array(array('time' => '18:31:00', 'artist' => 'LUIS RODRIGUEZ & DEN HARROW'), array('time' => '18:32:00', 'artist' => 'J BALVIN'), array('time' => '18:33:00', 'artist' => 'THE BLACK EYED PEAS FT J BALVIN'), array('time' => '18:34:00', 'artist' => 'THE BLACK EYED PEAS FT J BALVIN'), array('time' => '18:35:00', 'artist' => 'J BALVIN'));
I have to find at what time I can find this
$artista_inserito = 'THE BLACK EYED PEAS FT J BALVIN';
So I use a function to delimiter my array and even string
function multiexplode($delimiters, $string)
{
$ready = str_replace($delimiters, $delimiters[0], $string);
$launch = explode($delimiters[0], $ready);
return $launch;
}
// array with string delimeter
$array_delimiter_artisti = array(' FEAT ', ' feat ', ' FT ', ' ft ', ' + ', ' AND ', ' and ', ' E ', ' e ', ' VS ', ' vs ', ' FEAT. ', ' feat. ', ' FT. ', ' ft. ', ' VS. ', ' vs. ', ' , ', ' & ');
// I split the current artist
$artisti_inseriti = multiexplode($array_delimiter_artisti, $artista_inserito);
So I search the given string un my array
foreach ($input as $split) {
$time = $split['time'];
$artist = $split['artist'];
$lista_artisti = multiexplode($array_delimiter_artisti, $artist);
foreach ($lista_artisti as $nuovo) {
$artista_split = $nuovo;
// copy all new data in new array
$nuovo_array_dati[] = array('time' => $time, 'artist' => $artista_split);
}
}
foreach ($nuovo_array_dati as $controllo) {
$time = $controllo['time'];
$artist = $controllo['artist'];
foreach ($artisti_inseriti as $trova_artista) {
$artista_singolo = $trova_artista;
foreach ($controllo as $index => $a) {
if (strstr($a, $artista_singolo)) {
// now I can print where I found the given string $artista_inserito
echo "$artista_singolo is at $time ";
}
}
}
}
So this is my output
J BALVIN is at 18:32:00
THE BLACK EYED PEAS is at 18:33:00
J BALVIN is at 18:33:00
THE BLACK EYED PEAS is at 18:34:00
J BALVIN is at 18:34:00
J BALVIN is at 18:35:00
Can I improve this? Thanks
1 Answer 1
I have a bias toward regex because I'm generally comfortable with most techniques, so I'll recommend condensing your array of delimiters into a single regex pattern and employ preg_split()
to execute the explosion.
After splitting the search string into its separate artists, I am flipping the values & keys to optimize the lookup for later use in the nested loop.
Then as you iterate the haystack of artist times, you can re-use the splitting pattern, then iterate each individual artist and store the desired data for qualifying rows.
Code: (Demo)
$fullArtistTimes = [
['time' => '18:31:00', 'artist' => 'LUIS RODRIGUEZ & DEN HARROW'],
['time' => '18:32:00', 'artist' => 'J BALVIN'],
['time' => '18:33:00', 'artist' => 'THE BLACK EYED PEAS FT J BALVIN'],
['time' => '18:34:00', 'artist' => 'THE BLACK EYED PEAS FT J BALVIN'],
['time' => '18:35:00', 'artist' => 'J BALVIN']
];
$fullArtist = 'THE BLACK EYED PEAS FT J BALVIN';
$artistDelimiters = '~ (?:[+e,&]|and|f(?:ea)?t\.?|vs\.?) ~i';
$artists = array_flip(preg_split($artistDelimiters, $fullArtist));
$result = [];
foreach ($fullArtistTimes as $row) {
foreach (preg_split($artistDelimiters, $row['artist']) as $artist) {
if (isset($artists[$artist])) {
$result[] = "{$artist} is at {$row['time']}";
}
}
}
var_export($result);
Output:
array (
0 => 'J BALVIN is at 18:32:00',
1 => 'THE BLACK EYED PEAS is at 18:33:00',
2 => 'J BALVIN is at 18:33:00',
3 => 'THE BLACK EYED PEAS is at 18:34:00',
4 => 'J BALVIN is at 18:34:00',
5 => 'J BALVIN is at 18:35:00',
)
If this does not work for all of your cases, then I would need to see more test cases and your desired result before I could properly adjust my snippet.
-
\$\begingroup\$ Thanks, my only problem is the $artistDelimiters, I have to retrieve the delimiters from a mysql table where the user can add or remove some words, so the delimiters has to be more simple \$\endgroup\$pette– pette2020年04月08日 16:00:05 +00:00Commented Apr 8, 2020 at 16:00
-
\$\begingroup\$
'~ (?:' . implode('|', array_map(function($v){ return preg_quote($v, '~'); }, $databaseDelimiters)) . ') ~'
\$\endgroup\$mickmackusa– mickmackusa2020年04月08日 20:34:49 +00:00Commented Apr 8, 2020 at 20:34 -
\$\begingroup\$ If I use this I haven't same result
code $databaseDelimiters = array(' FEAT ', ' feat ', ' FT ', ' ft ', ' + ', ' AND ', ' and ', ' E ', ' e ', ' VS ', ' vs ', ' FEAT. ', ' feat. ', ' FT. ', ' ft. ', ' VS. ', ' vs. ', ' , ', ' & '); $artistDelimiters = '~ (?:' . implode('|', array_map(function ($v) { return preg_quote($v, '~'); }, $databaseDelimiters)) . ') ~'; $artists = array_flip(preg_split($artistDelimiters, $fullArtist));
\$\endgroup\$pette– pette2020年04月08日 22:04:51 +00:00Commented Apr 8, 2020 at 22:04 -
\$\begingroup\$ I'm sorry, I have to delete the blank spaces... it is right? Thanks \$\endgroup\$pette– pette2020年04月08日 22:13:14 +00:00Commented Apr 8, 2020 at 22:13
-
\$\begingroup\$ Ah yes, I forgot that bit. Yes,
trim()
them (before even saving them to the db -- keep your data tidy). \$\endgroup\$mickmackusa– mickmackusa2020年04月08日 22:24:34 +00:00Commented Apr 8, 2020 at 22:24
strstr()
to check the existence of a substring in a string -- usingstrpos()
is a better performer. I don't see any reason to check the time column's data. Why do you only use the first element of$array_delimiter_artisti
? \$\endgroup\$