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.
/**
* This function will return a shorter representation of the path.
* Each token in the path is given a certain weight based on it's position in the filename.
* Tokens with lower weight are removed first to achieve the desired length.
* Tokens at the start and end of the filename have higher weights, the last token has the heighest weight.
* @param filename The filename to operate on
* @param maxChars The maximum length of the returned filename.
* The length of the slash character is taken into account.
* Note: The function will always return a string that is at least 3 chars in length. This would be "..."
* @param allowPartials Allow tokens be partially visible instead of stripping them completely to fit the desired size
* @return The shortened filename
*/
public static function shorten( filename:String, maxChars:uint, allowPartials:Boolean = false ):String {
if( filename.length <= maxChars ) return filename;
var tokens:Array = filename.split( SLASH );
var weightedTokens:Array = new Array( tokens.length );
for( var i:uint = 0; i < weightedTokens.length; ++i ) {
var weight:Number = Math.abs( Math.sin( i / ( weightedTokens.length - 1 ) * Math.PI - Math.PI * 0.5 ) );
weightedTokens[ i ] = { token: tokens[ i ], weight: weight, position: i };
}
weightedTokens[ weightedTokens.length - 1 ].weight += 1; // Last token has the highest weight possible
weightedTokens.sortOn( "weight", Array.NUMERIC | Array.DESCENDING );
var currentLength:uint = 0;
var lastToken:uint = 0;
for( lastToken = 0; lastToken < weightedTokens.length; ++lastToken ) {
var currentTokenLength:uint = String( weightedTokens[ lastToken ].token ).length;
if( currentLength + currentTokenLength + 3 + ( lastToken * SLASH.length ) >= maxChars ) {
if( allowPartials ) {
var diff:int = maxChars - ( currentLength + currentTokenLength + 3 + ( lastToken * SLASH.length ) );
var finalDiff:int = diff - ( 3 + SLASH.length );
if( currentTokenLength + finalDiff > 0 ) {
weightedTokens[ lastToken ].token = String( weightedTokens[ lastToken ].token ).substr( 0, currentTokenLength + finalDiff ) + "...";
++lastToken;
}
}
break;
}
currentLength += currentTokenLength;
}
if( currentLength == 0 ) {
return "...";
}
if( lastToken < weightedTokens.length ) {
weightedTokens.splice( lastToken, weightedTokens.length - lastToken, { token: "...", weight: 0, position: weightedTokens[ lastToken ].position } );
}
weightedTokens.sortOn( "position", Array.NUMERIC );
var shortFilename:String = "";
for( var tokenIdx:uint = 0; tokenIdx < weightedTokens.length; ++tokenIdx ) {
if( tokenIdx > 0 ) shortFilename += SLASH;
shortFilename += String( weightedTokens[ tokenIdx ].token );
}
return shortFilename;
}

February 12th, 2008 at 22:42
Of course, SLASH has to be defined for this to work. And example would be:
public static const SLASH:String = “\\”;
October 31st, 2008 at 05:23
hi…
thanks…