A classic problem to split a string into its "root and suffix":
- (Stemming) The word "walk" is the base form for word "walking" (suffix is "ing");
- The file path
/var/www
is the base path of/var/www/myApp
; - The string
doi:10.1038/ncomms
is the URN-prefix fordoi:10.1038/ncomms7368
anddoi:10.1038/ncomms7666
; - The word "hello" is not a root for "walking" (suffix is "walking");
There are many ways to implement the same algorithm, so, what is the best? Examples in PHP, but valid for any language.
/**
* Splits a string by its root and sufix.
* @param $str string input
* @param $root string empty when no root, or start string
* @return array (rootFlag,sufix)
*/
function str_splitByRoot($str, $root){
...
}
Algorithms str_splitByRoot1()
, str_splitByRoot2()
, ..., str_splitByRoot5()
or other (show more if you know). All do the same thing, are valid solutions.
function str_splitByRoot1($str, $root){
if (strpos($str,$root)===0)
return array($root, substr($str, strlen($root)) );
else
return array( '', $str );
}
function str_splitByRoot2($str, $root){
$rootLen = strspn($str ^ $root, "\0");
return array( substr($root,0,$rootLen), substr($str,$rootLen) );
}
function str_splitByRoot3($str, $root){
$s = explode($root,$str);
return ( count($s)>1 && !array_shift($s) )?
array($root,join($root,$s)):
array('',$str);
}
function str_splitByRoot4($str, $root){
// to generalize need a secure regex, something like
// $regex = str_replace(array('/','.','-'),array('\\/','\\.','\\-'),$root);
$suffix = preg_replace("/^$root/",$str,1,$n);
return $n?
array($root,$suffix):
array('',$str);
}
function str_splitByRoot5($str, $root){
// need also $root translating as algorithm 4.
if (preg_match("/^$root(.+)$/",$str,$m))
return array($root,$m[1]);
else
return array('',$str);
}
The first is the traditional way. The last (algorithms 4 and 5) use regular expression, the second trim excess garbage from strings that are null terminated; and the third remember that the algorithm is a kind of split (explode
function).
All can be used with
function str_sepByRoot($str,$root){
return join(' * ',str_splitByRoot($str,$root));
}
print "\n".str_sepByRoot("walking","walk");
print "\n".str_sepByRoot("hello","walk");
print "\n".str_sepByRoot("walking-walk-walk","walk");
print "\n".str_sepByRoot("/var/www/myApp","/var/www/");
print "\n".str_sepByRoot("10.1038/ncomms7368","10.1038/ncomms");
returning
walk * ing * hello walk * ing-walk-walk /var/www/ * myApp 10.1038/ncomms * 7368