This site was apparently down earlier today (along with the rest of the hosted sites on weblogger.com), and I’ve been insanely busy here in DC, doing a dry run of my upcoming J2EE training course. But I’m done for the day and the site seems to be back and I would like to thank the readers of Scripting News for voting this as the best scripting weblog of 2001. In celebration, here’s one of my favorite scripts. (All right, it’s not really in celebration, because I wrote the script late last night and published it early this morning before Dave Winer announced that I had won. But it’s a nice coincidence, so let it slide.)
Here’s a Python script that I may try to expand into a chapter of my book. It pluralizes English nouns with about 99% accuracy. That is, assuming I haven’t made any stupid typos translating it from one language to another over the years. I first wrote it in Delphi, then translated it into Powerbuilder, and now I’m rewriting it the way it was meant to be written: using regular expressions.
The script will also give me a chance to explain the factory design pattern. It will probably end up becoming chapter 4 of “Dive Into Python”, by which time readers should already be familiar with multi-variable for loops, lambda functions, string functions, and other Python wonderfulness.
The script is hereby released under the same license as Python itself. Share and enjoy.
"""Pluralize English nouns"""
__author__ = "Mark Pilgrim (f8dy@diveintopython.org)"
__version__ = "$Revision: 1.1 $"
__date__ = "$Date: 2002/04/23 16:07:58 $"
__copyright__ = "Copyright (c) 2001 Mark Pilgrim"
__license__ = "Python"
import re
def makeRE(findPattern, source, target):
search = re.compile(findPattern, re.IGNORECASE).search
replace = lambda word, source=source, target=target: \
re.compile(source, re.IGNORECASE).sub(target, word)
return (search, replace)
samePlural = (lambda word: word in ('sheep', 'deer', 'fish', 'moose',
'aircraft', 'series', 'haiku', 'scissors'),
lambda word: word)
alwaysAddS = (lambda word: word in ('delf', 'pelf', 'human',
'roman', 'lowlife'),
lambda word: word + 's')
endsInMOUSE = makeRE('mouse$', 'mouse$', 'mice')
endsInLOUSE = makeRE('louse$', 'louse$', 'lice')
endsInCHILD = makeRE('child$', 'child$', 'children')
endsInBOOTH = makeRE('booth$', 'booth$', 'booths')
endsInFOOT = makeRE('foot$', 'foot$', 'feet')
endsInOOTH = makeRE('ooth$', 'ooth$', 'eeth')
endsInLEAF = makeRE('leaf$', 'leaf$', 'leaves')
endsInLOAF = makeRE('loaf$', 'loaf$', 'loaves')
endsInSIS = makeRE('sis$', 'sis$', 'ses')
endsInMAN = makeRE('man$', 'man$', 'men')
endsInIFE = makeRE('ife$', 'ife$', 'ives')
endsInEAU = makeRE('eau$', 'eau$', 'eaux')
endsInQUY = makeRE('quy$', 'quy$', 'quies')
endsInS = makeRE('[sxz]$’, ‘$’, ‘es’)
endsInH = makeRE(’[^aeioudgkprt]h$’, ‘$’, ‘es’)
endsInY = makeRE(’[^aeiou]y$’, ‘y$’, ‘ies’)
endsInLF = makeRE(’lf$’, ‘lf$’, ‘lves’)
rules = (samePlural, alwaysAddS, endsInMOUSE, endsInLOUSE,
endsInCHILD, endsInBOOTH,
endsInFOOT, endsInOOTH, endsInLEAF, endsInLOAF,
endsInSIS, endsInMAN, endsInIFE, endsInEAU, endsInQUY,
endsInS, endsInH, endsInY, endsInLF)
def plural(noun):
result = noun + ’s’
for matchesRule, pluralize in rules:
if matchesRule(noun):
result = pluralize(noun)
break
if noun == noun.upper():
result = result.upper()
return result

