Last active
September 1, 2016 10:43
-
-
Save yurynix/2496a18daebc872769b1a91baf787c84 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//////////// | |
/// | |
/// Delphin with RegExp x 131,568 ops/sec ±1.01% (85 runs sampled) | |
/// Delphin with for loop x 15,235 ops/sec ±0.72% (90 runs sampled) | |
/// Delphin with regex replace x 291,946 ops/sec ±1.08% (88 runs sampled) | |
/// Calypso x 323,048 ops/sec ±1.51% (87 runs sampled) | |
/// Fastest is Calypso | |
/// | |
//////////// | |
var trim = require( 'lodash/trim' ); | |
var Benchmark = require('benchmark'); | |
var suite = new Benchmark.Suite; | |
const wordsRegex = new RegExp( '\\S+', 'g' ); | |
function preventWidowDelphin1( text, wordsToKeep = 2 ) { | |
if ( typeof text !== 'string' ) { | |
return text; | |
} | |
const matches = []; | |
let match; | |
while ( match = wordsRegex.exec( text ) ) { | |
matches.push( match ); | |
} | |
if ( matches.length < 1 ) { | |
return text; | |
} | |
const startIndex = matches[ 0 ].index; | |
const endIndex = matches[ matches.length -1 ].index + matches[ matches.length - 1 ][ 0 ].length - 1; | |
const words = matches.map( match => match[ 0 ] ); | |
let result; | |
if ( words.length <= wordsToKeep ) { | |
result = words.join( '\xA0' ); | |
} else { | |
const endWords = words.splice( -wordsToKeep, wordsToKeep ); | |
result = words.join( ' ' ) + ' ' + endWords.join( '\xA0' ); | |
} | |
if ( startIndex === 0 && endIndex === text.length - 1 ) { | |
return result; | |
} | |
return text.substring( 0, startIndex ) + result + text.substring( endIndex, text.legth ); | |
} | |
function preventWidowDelphin2( text, wordsToKeep = 2 ) { | |
if ( typeof text !== 'string' ) { | |
return text; | |
} | |
const SPACES = { | |
'\xA0': true, | |
' ': true, | |
'\n': true, | |
'\r': true, | |
'\t': true | |
}; | |
let wordsCount = 0; | |
let inWord = false; | |
const newStringCharArray = new Array( text.length ); | |
for ( let i = text.length - 1; i >= 0; i-- ) { | |
if ( ! SPACES[ text[ i ] ] && ! inWord ) { | |
inWord = true; | |
wordsCount++; | |
} | |
if ( SPACES[ text[ i ] ] && inWord ) { | |
inWord = false; | |
} | |
if ( SPACES[ text[ i ] ] && wordsCount > 0 && ( text[ i ] === '\xA0' || text[ i ] === ' ' ) ) { | |
if ( wordsToKeep > wordsCount ) { | |
newStringCharArray.push( '\xA0' ); | |
} else { | |
// we change to regular space for the case when wordsToKeep is | |
// smaller than in a previous call to preventWidows | |
newStringCharArray.push( text[ i ] === '\xA0' ? ' ' : text[ i ] ); | |
} | |
} else { | |
newStringCharArray.push( text[ i ] ); | |
} | |
} | |
if ( wordsCount === 1 ) { | |
// special case, we shouldn't change anything | |
return text; | |
} | |
return newStringCharArray.reverse().join( '' ); | |
}; | |
function preventWidowDelphin3( text, wordsToKeep = 2 ) { | |
if ( typeof text !== 'string' ) { | |
return text; | |
} | |
let match; | |
let matches = []; | |
while ( ( match = wordsRegex.exec( text ) ) !== null ) { | |
matches.push( match ); | |
} | |
if ( matches.length < 1 ) { | |
return text; | |
} | |
let startIndex, | |
endIndex = matches[ matches.length - 1 ] .index + matches[ matches.length - 1 ][ 0 ].length - 1; | |
if ( matches.length < wordsToKeep ) { | |
startIndex = matches[ 0 ].index; | |
} else { | |
startIndex = matches[ matches.length - wordsToKeep ].index; | |
} | |
return text.replace( /\s+/g, ( replaceMatch, offset ) => { | |
if ( offset > startIndex && offset < endIndex ) { | |
return '\xA0'; | |
} else if ( replaceMatch === '\xA0' ) { | |
return ' '; | |
} | |
return replaceMatch; | |
} ); | |
} | |
function preventWidowCalypso( text, wordsToKeep = 2 ) { | |
let words, endWords; | |
if ( typeof text !== 'string' ) { | |
return text; | |
} | |
text = text && trim( text ); | |
if ( ! text ) { | |
return text; | |
} | |
words = text.match( /\S+/g ); | |
if ( ! words || 1 === words.length ) { | |
return text; | |
} | |
if ( words.length <= wordsToKeep ) { | |
return words.join( '\xA0' ); | |
} | |
endWords = words.splice( -wordsToKeep, wordsToKeep ); | |
return words.join( ' ' ) + ' ' + endWords.join( '\xA0' ); | |
} | |
// add tests | |
suite.add( 'Delphin with RegExp', function () { | |
preventWidowDelphin1( 'Millions of short, easy to remember domains will be available when the .blog domain goes live November 21.', 2 ); | |
}) | |
.add('Delphin with for loop', function () { | |
preventWidowDelphin2( 'Millions of short, easy to remember domains will be available when the .blog domain goes live November 21.', 2 ); | |
}) | |
.add('Delphin with regex replace', function () { | |
preventWidowDelphin3( 'Millions of short, easy to remember domains will be available when the .blog domain goes live November 21.', 2 ); | |
}) | |
.add('Calypso', function () { | |
preventWidowCalypso( 'Millions of short, easy to remember domains will be available when the .blog domain goes live November 21.', 2 ); | |
}) | |
// add listeners | |
.on('cycle', function( event ) { | |
console.log(String(event.target)); | |
} ) | |
.on('complete', function() { | |
console.log('Fastest is ' + this.filter( 'fastest' ).map( 'name' ) ); | |
}) | |
// run async | |
.run( { 'async': true } ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment