Short filenames based on weighted curve

Here is a small function that will shorten a filename based on a weighted curve.
I used a simple sine curve given the start and end of the filename the highest weights.

Actionscript:
  1. /**
  2. * This function will return a shorter representation of the path.
  3. * Each token in the path is given a certain weight based on it's position in the filename.
  4. * Tokens with lower weight are removed first to achieve the desired length.
  5. * Tokens at the start and end of the filename have higher weights, the last token has the heighest weight.
  6. * @param   filename The filename to operate on
  7. * @param   maxChars The maximum length of the returned filename.
  8. * The length of the slash character is taken into account.
  9. * Note: The function will always return a string that is at least 3 chars in length. This would be "..."
  10. * @param allowPartials Allow tokens be partially visible instead of stripping them completely to fit the desired size
  11. * @return The shortened filename
  12. */
  13. public static function shorten( filename:String, maxChars:uint, allowPartials:Boolean = false ):String {
  14.     if( filename.length <= maxChars ) return filename;
  15.    
  16.     var tokens:Array = filename.split( SLASH );
  17.     var weightedTokens:Array = new Array( tokens.length );
  18.    
  19.     for( var i:uint = 0; i <weightedTokens.length; ++i ) {
  20.         var weight:Number = Math.abs( Math.sin( i / ( weightedTokens.length - 1 ) * Math.PI - Math.PI * 0.5 ) );
  21.         weightedTokens[ i ] = { token: tokens[ i ], weight: weight, position: i };
  22.     }
  23.     weightedTokens[ weightedTokens.length - 1 ].weight += 1; // Last token has the highest weight possible
  24.    
  25.     weightedTokens.sortOn( "weight", Array.NUMERIC | Array.DESCENDING );
  26.    
  27.     var currentLength:uint = 0;
  28.     var lastToken:uint = 0;
  29.     for( lastToken = 0; lastToken <weightedTokens.length; ++lastToken ) {
  30.         var currentTokenLength:uint = String( weightedTokens[ lastToken ].token ).length;
  31.        
  32.         if( currentLength + currentTokenLength + 3 + ( lastToken * SLASH.length )>= maxChars ) {
  33.             if( allowPartials ) {
  34.                 var diff:int = maxChars - ( currentLength + currentTokenLength + 3 + ( lastToken * SLASH.length ) );
  35.                 var finalDiff:int = diff - ( 3 + SLASH.length );
  36.                 if( currentTokenLength + finalDiff> 0 ) {
  37.                     weightedTokens[ lastToken ].token = String( weightedTokens[ lastToken ].token ).substr( 0, currentTokenLength + finalDiff ) + "...";
  38.                     ++lastToken;
  39.                 }
  40.             }
  41.             break;
  42.         }
  43.        
  44.         currentLength += currentTokenLength;
  45.     }
  46.    
  47.     if( currentLength == 0 ) {
  48.         return "...";
  49.     }
  50.    
  51.     if( lastToken <weightedTokens.length ) {
  52.         weightedTokens.splice( lastToken, weightedTokens.length - lastToken, { token: "...", weight: 0, position: weightedTokens[ lastToken ].position } );
  53.     }
  54.     weightedTokens.sortOn( "position", Array.NUMERIC );
  55.    
  56.     var shortFilename:String = "";
  57.     for( var tokenIdx:uint = 0; tokenIdx <weightedTokens.length; ++tokenIdx ) {
  58.         if( tokenIdx> 0 ) shortFilename += SLASH;
  59.         shortFilename += String( weightedTokens[ tokenIdx ].token );
  60.     }
  61.    
  62.     return shortFilename;
  63. }

2 Responses to “Short filenames based on weighted curve”

  1. gencha Says:

    Of course, SLASH has to be defined for this to work. And example would be:
    public static const SLASH:String = “\\”;

  2. Russian Says:

    hi…

    thanks…

Leave a Reply

You must be logged in to post a comment.