Repository: scrapinghub/number-parser

Issue:
Support for simple fractions
We can add support for the simple fractions as well like three-fourth, half, etc.
Example:

> parse("I have a three-fourth cup of glass.")
I have a 3/4 cup of glass.

> parse_number("half")
1/2


Comments:

Patch:
diff --git a/README.rst b/README.rst
index b18ce13..1f1f62e 100644
--- a/README.rst
+++ b/README.rst
@@ -20,10 +20,10 @@ number-parser requires Python 3.6+.
 Usage
 =====
 
-The library provides three major APIs which corresponds to the following common usages.
+The library provides the following common usages.
 
-Interface #1: Multiple numbers
-------------------------------
+Converting numbers in-place
+---------------------------
 
 Identifying the numbers in a text string, converting them to corresponding numeric values while ignoring non-numeric words.
 This also supports ordinal number conversion (for English only).
@@ -36,9 +36,9 @@ This also supports ordinal number conversion (for English only).
 >>> parse("First day of year two thousand")
 '1 day of year 2000'
 
+Parsing a number
+----------------
 
-Interface #2: Single number
---------------------------------
 Converting a single number written in words to it's corresponding integer.
 
 >>> from number_parser import parse_number
@@ -46,11 +46,10 @@ Converting a single number written in words to it's corresponding integer.
 2020
 >>> parse_number("not_a_number")
 
+Parsing an ordinal
+------------------
 
-Interface #3: Single number Ordinal
--------------------------------------
-
-Converting a single ordinal number written in words to it's corresponding integer. (Support for only English)
+Converting a single ordinal number written in words to its corresponding integer. (Support for English only)
 
 >>> from number_parser import parse_ordinal
 >>> parse_ordinal("twenty third")
@@ -58,6 +57,19 @@ Converting a single ordinal number written in words to it's corresponding intege
 >>> parse_ordinal("seventy fifth")
 75
 
+Parsing a fraction
+------------------
+
+Converting a fractional number written in words to its corresponding integral fraction. (Support for English only)
+
+>>> from number_parser import parse_fraction
+>>> parse_fraction("forty two divided by five hundred and six")
+'42/506'
+>>> parse_fraction("one over two")
+'1/2'
+>>> parse_fraction("forty two / one million")
+'42/1000000'
+
 
 Language Support
 ----------------
diff --git a/number_parser/__init__.py b/number_parser/__init__.py
index 8efbc8a..472179e 100644
--- a/number_parser/__init__.py
+++ b/number_parser/__init__.py
@@ -1,1 +1,1 @@
-from number_parser.parser import parse, parse_number, parse_ordinal
+from number_parser.parser import parse, parse_number, parse_ordinal, parse_fraction
diff --git a/number_parser/parser.py b/number_parser/parser.py
index 2afbf3a..e0d67c2 100644
--- a/number_parser/parser.py
+++ b/number_parser/parser.py
@@ -268,6 +268,36 @@ def parse_number(input_string, language=None):
     return None
 
 
+def parse_fraction(input_string, language=None):
+    """Converts a single number written in fraction to a numeric type"""
+    if not input_string.strip():
+        return None
+
+    if language is None:
+        language = _valid_tokens_by_language(input_string)
+
+    FRACTION_SEPARATORS = ["divided by", "over", "by", "/"]
+
+    for separator in FRACTION_SEPARATORS:
+        position_of_separator = input_string.find(separator)
+
+        if position_of_separator == -1:
+            continue
+
+        string_before_separator = input_string[:position_of_separator]
+        string_after_separator = input_string[position_of_separator + len(separator):]
+
+        number_before_separator = parse_number(string_before_separator, language)
+        number_after_separator = parse_number(string_after_separator, language)
+
+        if number_before_separator is None or number_after_separator is None:
+            return None
+
+        return f'{number_before_separator}/{number_after_separator}'
+
+    return None
+
+
 def parse(input_string, language=None):
     """
     Converts all the numbers in a sentence written in natural language to their numeric type while keeping


Test patch:
diff --git a/tests/test_number_parsing.py b/tests/test_number_parsing.py
index 216bfd6..2de6d09 100644
--- a/tests/test_number_parsing.py
+++ b/tests/test_number_parsing.py
@@ -1,5 +1,5 @@
 import pytest
-from number_parser import parse, parse_number
+from number_parser import parse, parse_number, parse_fraction
 from number_parser.parser import LanguageData, parse_ordinal
 
 
@@ -121,6 +121,33 @@ def test_parse_sentences_ordinal(expected, test_input, lang):
     assert parse(test_input, lang) == expected
 
 
+
+@pytest.mark.parametrize(
+    "test_input,expected,lang",
+    [
+        # empty / not-a-number
+        ('', None, None),
+        ('example of sentence', None, None),
+        # numeric
+        ('32', None, None),
+        (' 3 ', None, None),
+        # en
+        ('eleven', None, 'en'),
+        ('one hundred and forty two by a sentence', None, 'en'),
+        ('sentence / eleven', None, 'en'),
+        ('one hundred and forty two by eleven', '142/11', 'en'),
+        ('one hundred and forty two divided by eleven', '142/11', 'en'),
+        ('one hundred and forty two / eleven', '142/11', 'en'),
+        ('one hundred and forty two over eleven', '142/11', 'en'),
+        ('two million three thousand and nineteen/two thousand and nineteen', '2003019/2019', 'en'),
+        ('billion over nineteen billion and nineteen', '1000000000/19000000019', 'en'),
+
+    ]
+)
+def test_parse_fraction(expected, test_input, lang):
+    assert parse_fraction(test_input, language=lang) == expected
+
+
 def test_LanguageData_unsupported_language():
     with pytest.raises(ValueError):
         LanguageData('xxxx')