如果有一个单词,可能是也可能不是单数形式的名词,你会如何产生复数形式?
基于这个NLTK tutorial和informal list多元化规则,我写了这个简单的函数:
def plural(word):
"""
Converts a word to its plural form.
"""
if word in c.PLURALE_TANTUMS:
# defective nouns, fish, deer, etc
return word
elif word in c.IRREGULAR_NOUNS:
# foot->feet, person->people, etc
return c.IRREGULAR_NOUNS[word]
elif word.endswith('fe'):
# wolf -> wolves
return word[:-2] + 'ves'
elif word.endswith('f'):
# knife -> knives
return word[:-1] + 'ves'
elif word.endswith('o'):
# potato -> potatoes
return word + 'es'
elif word.endswith('us'):
# cactus -> cacti
return word[:-2] + 'i'
elif word.endswith('on'):
# criterion -> criteria
return word[:-2] + 'a'
elif word.endswith('y'):
# community -> communities
return word[:-1] + 'ies'
elif word[-1] in 'sx' or word[-2:] in ['sh', 'ch']:
return word + 'es'
elif word.endswith('an'):
return word[:-2] + 'en'
else:
return word + 's'
但我认为这是不完整的。有更好的方法吗?
答案 0 :(得分:28)
pattern-en包(对于python 2.5+,但还没有python 3)提供pluralization
>>> import pattern.en
>>> pattern.en.pluralize("dog")
'dogs'
>>>
答案 1 :(得分:11)
支持python 3的另一个选项是Inflect。
import inflect
engine = inflect.engine()
plural = engine.plural(your_string)
答案 2 :(得分:3)
首先,值得注意的是,正如the FAQ所解释的那样,WordNet无法生成复数形式。
如果你想使用它,你可以。使用Morphy,WordNet可能会为许多名词生成复数...但它仍然无法帮助大多数不规则名词,如“儿童”。
无论如何,从Python使用WordNet的简单方法是通过NLTK。其中一个NLTK HOWTO文档解释了WordNet Interface。 (当然,在没有指定语料库的情况下使用NLTK会更容易,但这不是你要求的。)
WordNet有一个名为pywordnet
的低级API,但我相信它已不再维护(它成为NLTK集成的基础),并且仅适用于旧版本的Python(可能是2.7,但是不是3.x)和WordNet(只有2.x)。
或者,您始终可以使用ctypes
或cffi
或构建自定义绑定来访问C API,或使用Jython而不是CPython访问Java API。
或者,当然,您可以通过subprocess
调用命令行界面。
无论如何,至少在某些安装中,如果你给简单的Morphy接口一个单数名词,它将返回它的复数,而如果你给它一个复数名词,它将返回它的单数。所以:
from nltk.corpus import wordnet as wn
assert wn.morphy('dogs') == 'dog'
assert wn.morphy('dog') == 'dog'
这实际上并没有记录,甚至暗示是真的,事实上OP显然不是这样,所以我不确定我是否愿意依赖它(即使它恰好工作了)在你的电脑上。)
的另一种方式记录有效,因此您可以编写一些规则来应用所有可能的英语复数规则,在每个规则上调用morphy
,然后返回第一个规则起始字符串是正确的复数。
然而,通过盲目地应用相同类型的规则,记录它的工作方式是有效的。因此,例如,它会正确地告诉您doges
不是dog
的复数形式 - 但不是因为它知道dogs
是正确的答案;只因为它知道doge
是一个不同的单词,它比“+ s”规则更喜欢“+ s”规则。所以,这不会有所帮助。
此外,如上所述,它没有任何不规则复数的规则 - WordNet不知道children
和child
以任何方式相关。
此外,wn.morphy('reckless')
将返回'reckless'
而不是None
。如果你想要,你必须首先测试它是否是名词。你可以坚持使用相同的界面,虽然它有点hacky:
def plural(word):
result = wn.morphy(word)
noun = wn.morphy(word, wn.NOUN)
if noun in (word, result):
return result
要做到这一点,你实际上需要添加一个复数数据库,而不是试图欺骗WordNet做一些它不能做的事情。
此外,一个单词可以有多种含义,它们可以有不同的复数,有时甚至有多个复数用于相同的含义。所以你可能想从(lemma for s in synsets(word, wn.NOUN) for lemma in s.lemmas if lemma.name == word)
开始,然后获得所有适当的复数,而不是只返回“复数”。