Hey, I'm looking for the best way to loop over an array for matches, and non matches. Basically I want to output a tag html for when there is a tag match, and a different html for when there isn't a match. The code has to support both arrays having a different amount of data. Thanks for reading. $stmGenres = $db->prepare('SELECT `tag` FROM `tags` WHERE `username` = ? AND `category` = ?'); $stmGenres->execute(array($poster->return_username(), 'genres')); $posterGenres = $stmGenres->fetchAll(); $stmUserGenres = $db->prepare('SELECT `tag` FROM `tags` WHERE `username` = ? AND `category` = ?'); $stmUserGenres->execute(array($poster->return_username(), 'genres')); $userGenres = $stmUserGenres->fetchAll(); if(count($posterGenres) >= 1) { echo '<div id="browse-search-tray" class="buffer-top"> <h4 class="sm-buffer-bottom">Genres</h4>'; foreach($posterGenres as $key => $val) { foreach($userGenres as $key2 => $val2) { if($posterGenres[$key]['tag'] == $userGenres[$key2]['tag']) { // match echo '<span class="label label-default tagselected" style="margin-bottom:4px;">'.$posterGenres[$key]['tag'].'</span>'; }else{ // no match echo '<span class="label label-default tag" style="margin-bottom:4px;">'.$posterGenres[$key]['tag'].'</span>'; } } } echo '</div>'; } Code (markup):
Unless I am reading this wrong $posterGenres is the same as $userGenres. Both queries are the same and will result in the same array. Besides that you can speed things up by having an array of user genres : userGenres = array(1 => true, 2 => true, etc..); and doing and isset check when looping through posterGenres. This will save you the looping.
or even an array_key_exists or in_array. I suspect the usernames are meant to be looking at the author of an article and the logged in user (normally different).
Yes, sorry, I didn't notice that typo. Those are supposed to be two different user objects. I'll fix that and see how it's running
array_key_exists won't work because of multidimensional arrays. I fixed the code above. In the select it's just $poster->return_username() and $user->return_username() It's outputting to many tags because of the double foreach loops.
Because you're learning as you go I'd tend to break this down to steps. get your data process your data output your data so, without testing, I'd probably start with this <?php $stmGenres = $db->prepare('SELECT `tag` FROM `tags` WHERE `username` = ? AND `category` = ?'); $stmGenres->execute(array($poster->return_username(), 'genres')); $posterGenres = $stmGenres->fetchAll(); $stmUserGenres = $db->prepare('SELECT `tag` FROM `tags` WHERE `username` = ? AND `category` = ?'); $stmUserGenres->execute(array($user->return_username(), 'genres')); $userGenres = $stmUserGenres->fetchAll(); $matches = array(); if (count($posterGenres) > 0) { foreach ($posterGenres as $key => $val) { $tag = $posterGenres[$key]['tag']; foreach ($userGenres as $key2 => $val2) { if ($tag == $userGenres[$key2]['tag']) { // even if it's in the array there's no harm in overwriting the value $matches[$tag] = 'tagselected'; } else { // just in case a tag can turn up twice, take the check out if that's not possible if (!array_key_exists($tag, $matches)) { $matches[$tag] = 'tag'; } } } } } // now that we have our tags all sorted out we can output them to the browser if (count($matches) > 0) { echo '<div id="browse-search-tray" class="buffer-top"> <h4 class="sm-buffer-bottom">Genres</h4>'; foreach ($matches as $tag => $class) { echo "<span class='label label-default {$class}' style='margin-bottom:4px;'>{$tag}</span>"; } echo '</div>'; } Code (markup):
span class="label if it's a label why isn't it a label tag? Lemme guess, bootcrap or something similar? You only select TAG, so why are you wasting time returning an index and accessing the array by index?!? There is no reason to waste time counting ASSUMING those are two different query (they aren't right now as @ThePHPMaster pointed out), the rest of it could simply be: // again, why the hell are these two the same query?!? // taking a WILD guess as to what it should be $stmt = $db->prepare(' SELECT tag FROM tags WHERE username = ? '); $stmt->execute([$poster->return_username()]); $userKeys = $stmt->fetchAll(); $stmt = $db->prepare(' SELECT tag FROM tags WHERE category = ? '); $stmt->execute(['genres']); $genreKeys = $stmt->fetchAll(); $result = array_merge( array_fill_keys($userKeys, 'tag'), array_fill_keys($genreKeys, 'tag'), array_fill_keys( array_intersect($userKeys, $genreKeys), 'tagCategory' ) ); if (count($result)) { echo ' <div id="browse-search-tray"> <h2>Genres</h2>'; foreach ($result as $tagName => $className) echo ' <span class="', $className, '">', $tagName, '</span>'; echo ' </div>'; } Code (markup): Though a bit wasteful of memory, it's a lot simpler -- I'm assuming your logic is you want ALL tags if the category matches OR the user matches, not BOTH, but if they exist in both give it a different class? You get a list of those that match your desired genre, a list of the tags for the user, you merge the two into an associative array keyed by tag, then merge and intersection of the two with the higher priority class. When using array_merge the latter array parameter will overwrite an existing index in the associative result. So lets say for user you had: red, blue, green, yellow ... and for genre you had: blue, yellow, orange, purple The result of that array merge and intersect should be: [ 'red' => 'cat', 'blue' => 'catselected', 'green' => cat', 'yellow' => 'catselected', 'orange' => 'cat', 'purple' => 'cat' ] Code (markup): Otherwise what you are doing makes no sense whatsoever... or do you only want the ones in user that if the genre tag exists select them... It's REALLY unclear what your data is and what you're trying to do with it.