singplur.py 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import re
  2. SINGULARS = (
  3. (r'ives', 'ife'),
  4. (r'ves', 'f'),
  5. (r'zes', ''),
  6. (r'men', 'man'),
  7. (r'matrices', 'matrix'),
  8. (r'([aeiou])ys', '\\1y'),
  9. (r'([^aeiou])ies', '\\1y'),
  10. (r'([^aeiou])ices$','\\1ice'),
  11. (r'ices', 'ex'),
  12. (r'([sxz]|[cs]h)es$', '\\1'),
  13. (r'eet', 'oot'),
  14. (r'ies', 'y'),
  15. (r'i', 'us'),
  16. (r's', ''),
  17. )
  18. PLURALS = (
  19. (r'man$', 'men'),
  20. (r'([aeiou]y)', '\\1s'),
  21. (r'([^aeiou])y', '\\1ies'),
  22. (r'([sxz]|[cs]h)', '\\1es'),
  23. (r'(cello|disco|hairdo|logo|patio|photo|piano|radio|chef|cliff|ref|roof)',
  24. '\\1s'),
  25. (r'o', 'oes'),
  26. (r'fe', 'ves'),
  27. (r'eaf', 'eaves'),
  28. (r'[ei]x', 'ices'),
  29. (r'us', 'i'),
  30. (r'', 's'),
  31. )
  32. EXCEPTIONS_SINGULAR = {
  33. 'person': 'people',
  34. 'child': 'children',
  35. 'ox': 'oxen',
  36. 'foot': 'feet',
  37. 'tooth': 'teeth',
  38. 'goose': 'geese',
  39. 'mouse': 'mice',
  40. 'louse': 'lice',
  41. 'man': 'men',
  42. 'woman': 'women',
  43. 'goose': 'geese',
  44. }
  45. EXCEPTIONS_PLURAL = dict([p[::-1] for p in EXCEPTIONS_SINGULAR.iteritems()])
  46. SAME = ('equipment', 'information', 'rice', 'money', 'species', 'series',
  47. 'fish', 'sheep', 'deer', 'tuna', 'salmon', 'trout')
  48. def apply_rules(word, rules):
  49. word = word.strip()
  50. if word in SAME:
  51. return word
  52. for pattern,replacement in rules:
  53. word, n = re.subn(pattern + '$', replacement, word)
  54. if n:
  55. break
  56. return word
  57. def singularize(word):
  58. if word in EXCEPTIONS_PLURAL:
  59. return EXCEPTIONS_PLURAL[word]
  60. return apply_rules(word, SINGULARS)
  61. def pluralize(word):
  62. if word in EXCEPTIONS_SINGULAR:
  63. return EXCEPTIONS_SINGULAR[word]
  64. return apply_rules(word, PLURALS)