Forum Moderators: coopster
I've got a client (an ex English professor) who is absoluty a demon when it comes to "singular/plural" text display on his site.
"It's never '1 adults', it's '1 adult'" and so on. He's right of course... and it just makes the output look more professional overall.
So far, I've tackled this issue with various conditional statements used as necessary, like:
$prevAdults == 0 ¦¦ $prevAdults > 1? $adultForm .= ' Adults' : $adultForm .= ' Adult';
This "solution" is getting somewhat time consuming to implement, and I thought it would be a perfect candidate for a function.
After researching the (American) English rules - given the many possible variations depending upon how and where a particular word is used, this has become more of a daunting nut to crack as I had initially expected.
Does anyone know of a pre-rolled solution to this that I can simply plug in an use?
Neophyte
function noun($num,$word,$plural_suffix) {
return ($num == 1)?$word:$word.$plural_suffix;
}
Examples:
echo noun(4,'bus','es'); #echos 'buses'
echo noun(1,'bus','es'); #echos 'bus'
echo noun(3,'cat','s'); #echos 'cats'
Hope this helps :)
So you could create array of words like this
$plural= array(
'bus' => 'buses',
'cat' => 'cats',
'mouse' => 'mice',
'index' => 'indices',
...
);
function noun($num,$word) {
global $plural;
return ($num == 1)? $word : $plural[$word];
}
echo noun(4,'bus'); #echos 'buses'
echo noun(1,'bus'); #echos 'bus'
echo noun(3,'mouse'); #echos 'mice'
$plural_rules = array( '/(x¦ch¦ss¦sh)$/' => '\1es', # search, switch, fix, box, process, address
'/series$/' => '\1series',
'/([^aeiouy]¦qu)ies$/' => '\1y',
'/([^aeiouy]¦qu)y$/' => '\1ies', # query, ability, agency
'/(?:([^f])fe¦([lr])f)$/' => '\1\2ves', # half, safe, wife
'/sis$/' => 'ses', # basis, diagnosis
'/([ti])um$/' => '\1a', # datum, medium
'/person$/' => 'people', # person, salesperson
'/man$/' => 'men', # man, woman, spokesman
'/child$/' => 'children', # child
'/(.*)status$/' => '\1statuses',
'/s$/' => 's', # no change (compatibility)
'/$/' => 's'
)
mouse = mice
So with the existing function that has the associative array in there (or stored sepereate in global var) to itterate through the array until the match is found depending on parameters fead to the function i.e. feed NULL as $plurar_suffix:
eelixduppy's code with modifications:
function noun($num,$word,$plural_suffix) {
//Array of awkward words - could be stored in a config file and made global by $_SERVER['wordArray']
$wordArray = array (
'mouse' => 'mice',
'index' => 'indeces'
);
//For loop to check for a match - use < count here as we start on 0 and the
//array count will start from 1, if we use <= then we perform an itteration for no reason at the end
for($x=0;$x<count($wordArray);$x++){
//If statement to check for awkward words - only if num > (greater than) 1
//think this is right havent tested it - concept is there
//Possibly use!empty() for checking process
if( $num>1 && isset($wordArray[$word]) ){
$word=$wordArray[$word];
return $word;
//Breaks out of the loop as we found a match
break;
//No awkward word match so process as normal
}else{
return ($num == 1)?$word:$word.$plural_suffix;
}
}
}
Examples:
echo noun(4,'bus','es'); #echos 'buses'
echo noun(1,'bus','es'); #echos 'bus'
echo noun(3,'mouse',NULL); #echos 'mice'
echo noun(1,'mouse',NULL); #echos 'mouse'
NOTES: Just looking over it a little in efficient as it will loop through the array till it finds a match and if not then it will perform the last operation using the plurar parameter.
AFTERTHOUGHT: You could use the $plural_suffix to trigger the type of operation in the function i.e. if plural_suffix == 0/FALSE/NULL then check and replace via the array, otherwise check and replace via other method?!?
ADDITIONAL AFTERTHOIGHT: Just reading joes post there thats great but you would need an array for all possible words :-s eek, if what i wrote works then all you need to do is find out the awkward words populate the array, preferably global in a config.inc.php file and your done, other words taken care of using the $plural_appendix parameter.
Spank me if im wrong...
[edited by: PSWorx at 4:38 pm (utc) on Mar. 14, 2007]
something like this (not tested):
function getplural($word) {
$result = $word;
foreach($rules as $pattern=>$repl) {
$result = preg_replace ($pattern, $repl, $word);
if ($result!= $word) break; // leave if plural found
}
return $result;
}
echo getplural('search') would return "searches".
But that array will have to be populated with all non-regular words anyway :(
function noun($num,$singular,$plural) {
return ($num == 1)?$singular:$plural;
}
Wow, of all the posts I've done on WebmasterWorld I never expacted so much action on this one!
Thank you all for weighing in - all interesting solutions.
From a "maintaining associative arrays" standpoint, I'm leaning toward exlixduppy's final solution - without the suffix but just the complete plural so I can stay out of the fire with "mice", "indices", etc.
>>>>>>>
function noun($num, $singular, $plural)
{
return ($num == 1)? $singular : $plural;
}
echo noun(0, 'mouse', 'mice');
>>>>>>>
Thank you all (as always!) for your guidance!
Neophyte