Search code examples
phpforeachlimittag-cloud

Limit a for each loop in a tag cloud


I have the following tag cloud.

$rows = $db->loadObjectList();
foreach ($rows as $row)
{
$strAllTags .= $row->caption . ","; 
}

// Store frequency of words in an array
$freqData = array(); 

// Get individual words and build a frequency table
foreach( explode(",", $strAllTags) as $word )
{
// For each word found in the frequency table, increment its value by one
array_key_exists( trim($word), $freqData ) ? $freqData[ trim($word) ]++ : $freqData[ trim($word) ] = 0;
}


function getCloud( $data = array(), $minFontSize = 12, $maxFontSize = 32 )
{
$minimumCount = min( array_values( $data ) );
$maximumCount = max( array_values( $data ) );
$spread       = $maximumCount - $minimumCount;
$cloudHTML    = '';
$cloudTags    = array();

$spread = 55;

foreach( $data as $tag => $count )
{
            if ($count > 4)
            {
    $size = $minFontSize + ( $count - $minimumCount ) 
        * ( $maxFontSize - $minFontSize ) / $spread;
    $cloudTags[] = '[[a style="font-size: ' . floor( $size ) . 'px' 
    . '" class="tag_cloud" href="/home?func=search&searchfield=' . $tag 
    .  '"]]' 
    . htmlspecialchars( stripslashes( $tag ) ) . '[[/a]]';
           }
}

return join( "\n", $cloudTags ) . "\n";
}   
echo getCloud($freqData);
?>

It works fine, I simply need to limit it to the top 20 results, any ideas as to how to do this best?

Thanks, let me know if you need to see the rest of the code.


Solution

  • If your array isn't already sorted, you can use arsort() to sort it by the highest results. Then you can use array_slice() to create a new array with just the first 20 array elements:

    arsort($data);
    $data = array_slice($data, 0, 20);
    

    arsort means "associative reverse sort". This just means that it acts on associative arrays, maintaining their keys, and sorts the array in "reverse" (i.e. high to low) order by it's values.

    array_slice just "slices" up an existing array. In this example, it says "take the $data array, and return a new array containing 20 of its values, starting from the first one.

    To address the point you made in the comments about this causing the tags to also be displayed in order by size, when you want them to be random. You can accomplish this by using shuffle on the array after you grab the top 20 records:

    arsort($data);
    $data = array_slice($data, 0, 20);
    shuffle($data);