Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new parse_fraction function for simple fractions added with test data #60

Merged
merged 11 commits into from
Mar 24, 2021
28 changes: 20 additions & 8 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand All @@ -36,19 +36,18 @@ 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
>>> parse_number("two thousand and twenty")
2020
>>> parse_number("not_a_number")


Interface #3: Single number Ordinal
-------------------------------------
Parsing an ordinal
------------------

Converting a single ordinal number written in words to it's corresponding integer. (Support for only English)

Expand All @@ -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 it's corresponding integeral fraction. (Support for only English)
Gallaecio marked this conversation as resolved.
Show resolved Hide resolved

>>> 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
----------------
Expand Down
2 changes: 1 addition & 1 deletion number_parser/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from number_parser.parser import parse, parse_number, parse_ordinal
from number_parser.parser import parse, parse_number, parse_ordinal, parse_fraction
29 changes: 29 additions & 0 deletions number_parser/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,35 @@ def parse_number(input_string, language=None):
return int(number_built[0])
return None

Gallaecio marked this conversation as resolved.
Show resolved Hide resolved
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", "/"]
Gallaecio marked this conversation as resolved.
Show resolved Hide resolved

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 == None or number_after_separator == None:
Gallaecio marked this conversation as resolved.
Show resolved Hide resolved
return None

return str(number_before_separator) + '/' + str(number_after_separator)
Gallaecio marked this conversation as resolved.
Show resolved Hide resolved

return None


def parse(input_string, language=None):
"""
Expand Down
29 changes: 28 additions & 1 deletion tests/test_number_parsing.py
Original file line number Diff line number Diff line change
@@ -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


Expand Down Expand Up @@ -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')