Commits

Mikhail Korobov committed 50a0a76 Merge

Merge pull request #28 from ivirabyan/master

Согласование слова с числительным

Comments (0)

Files changed (2)

pymorphy2/analyzer.py

     _dict = None
     """ :type _dict: pymorphy2.opencorpora_dict.Dictionary """
 
+    _plural_forms = (
+        set(['sing', 'nomn']),
+        set(['sing', 'gent']),
+        set(['plur', 'nomn']),
+        set(['plur', 'gent']),
+    )
+
     def inflect(self, required_grammemes):
         res = self._morph._inflect(self, required_grammemes)
         return None if not res else res[0]
 
+    def pluralize(self, num):
+        if (num % 10 == 1) and (num % 100 != 11):
+            index = 0
+        elif (num % 10 >= 2) and (num % 10 <= 4) and (num % 100 < 10 or num % 100 >= 20):
+            index = 1
+        else:
+            index = 2
+
+        if self.tag.POS == 'NOUN' and self.tag.case != 'nomn':
+            if index == 0:
+                grammemes = set(['sing', self.tag.case])
+            elif self.tag.case == 'accs' and index == 2:
+                grammemes = self._plural_forms[3]
+            else:
+                grammemes = set(['plur', self.tag.case])
+        elif index == 0:
+            grammemes = self._plural_forms[0]
+        elif self.tag.POS == 'NOUN' and index == 1:
+            grammemes = self._plural_forms[1]
+        elif self.tag.POS in ('ADJF', 'PRTF') and self.tag.gender == 'femn' and index == 1:
+            grammemes = self._plural_forms[2]
+        else:
+            grammemes = self._plural_forms[3]
+        return self.inflect(grammemes)
+
     @property
     def lexeme(self):
         """ A lexeme this form belongs to. """

tests/test_pluralize.py

+# -*- coding: utf-8 -*-
+from __future__ import absolute_import, unicode_literals
+import pytest
+
+from .utils import morph
+
+
+@pytest.mark.parametrize(('word', 'result'), [
+    # прилагательные
+    ("бесплатная", ["бесплатная", "бесплатные", "бесплатных"]),
+    ("бесплатный", ["бесплатный", "бесплатных", "бесплатных"]),
+    
+    # числительные
+    ("первый", ["первый", "первых", "первых"]),
+    ("первая", ["первая", "первые", "первых"]),
+
+    # существительные
+    ("книга", ["книга", "книги", "книг"]),
+    ("болт", ["болт", "болта", "болтов"]),
+
+    # причастия
+    ("летящий", ["летящий", "летящих", "летящих"]),
+    ("летящая", ["летящая", "летящие", "летящих"]),
+])
+def test_plural_forms(word, result):
+    parsed = morph.parse(word)
+    assert len(parsed)
+    for plural, num in zip(result, [1, 2, 5]):
+        assert parsed[0].pluralize(num).word == plural
+
+
+@pytest.mark.parametrize(('word', 'case', 'result'), [
+    ("книги", 'gent', ["книги", "книг", "книг"]),
+    ("книге", 'datv', ["книге", "книгам", "книгам"]),
+    ("книгу", 'accs', ["книгу", "книги", "книг"]),
+    ("книгой", 'ablt', ["книгой", "книгами", "книгами"]),
+    ("книге", 'loct', ["книге", "книгах", "книгах"]),
+])
+def test_plural_inflected(word, case, result):
+    parsed = [p for p in morph.parse(word) if p.tag.case == case]
+    assert len(parsed)
+    for plural, num in zip(result, [1, 2, 5]):
+        assert parsed[0].pluralize(num).word == plural
+
+
+@pytest.mark.parametrize(('word', 'num', 'result'), [
+    ("лопата", 0, "лопат"),
+    ("лопата", 1, "лопата"),
+    ("лопата", 2, "лопаты"),
+    ("лопата", 4, "лопаты"),
+    ("лопата", 5, "лопат"),
+    ("лопата", 6, "лопат"),
+    ("лопата", 11, "лопат"),
+    ("лопата", 12, "лопат"),
+    ("лопата", 15, "лопат"),
+    ("лопата", 21, "лопата"),
+    ("лопата", 24, "лопаты"),
+    ("лопата", 25, "лопат"),
+    ("лопата", 101, "лопата"),
+    ("лопата", 103, "лопаты"),
+    ("лопата", 105, "лопат"),
+    ("лопата", 111, "лопат"),
+    ("лопата", 112, "лопат"),
+    ("лопата", 151, "лопата"),
+    ("лопата", 122, "лопаты"),
+    ("лопата", 5624, "лопаты"),
+    ("лопата", 5431, "лопата"),
+    ("лопата", 7613, "лопат"),
+    ("лопата", 2111, "лопат"),
+])
+def test_plural_num(word, num, result):
+    parsed = morph.parse(word)
+    assert len(parsed)
+    assert parsed[0].pluralize(num).word == result
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.