Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 27 additions & 15 deletions pythainlp/util/wordtonum.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,15 @@
return Tokenizer(custom_dict=_valid_tokens)


def _check_is_thainum(word: str) -> tuple[bool, Optional[str]]:
def _check_is_thainum(
word: str,
next_word: str = "",
thainum: Optional[list[str]] = None,
) -> tuple[bool, Optional[str]]:
if word == "ศูนย์" and thainum is not None:

Check failure on line 65 in pythainlp/util/wordtonum.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "ศูนย์" 3 times.

See more on https://sonarcloud.io/project/issues?id=PyThaiNLP_pythainlp&issues=AaCqyabffyzltGVdETlu&open=AaCqyabffyzltGVdETlu&pullRequest=1503
if "จุด" in thainum or next_word == "จุด":
return (True, "num")
return (False, None)
for j in _digits:
if j in word:
return (True, "num")
Expand Down Expand Up @@ -167,6 +175,16 @@
return num


def _flush(thainum: list[str], result: list[str]) -> None:
has_digit = any(
w == "ศูนย์" or _check_is_thainum(w)[1] == "num" for w in thainum
)
if has_digit:
result.append(str(words_to_num(thainum)))
else:
result.extend(thainum)


def text_to_num(text: str) -> list[str]:
"""Thai text to list of Thai words with floating point numbers

Expand All @@ -188,25 +206,19 @@
last_index = -1
list_word_new = []
for i, word in enumerate(_temp):
if (
_check_is_thainum(word)[0]
and last_index + 1 == i
and i + 1 == len(_temp)
):
next_word = _temp[i + 1] if i + 1 < len(_temp) else ""
isthainum = _check_is_thainum(word, next_word, thainum)[0]
if isthainum and last_index + 1 == i and i + 1 == len(_temp):
thainum.append(word)
list_word_new.append(str(words_to_num(thainum)))
elif _check_is_thainum(word)[0] and last_index + 1 == i:
_flush(thainum, list_word_new)
elif isthainum and last_index + 1 == i:
thainum.append(word)
last_index = i
elif _check_is_thainum(word)[0]:
elif isthainum:
thainum.append(word)
last_index = i
elif (
not _check_is_thainum(word)[0]
and last_index + 1 == i
and last_index != -1
):
list_word_new.append(str(words_to_num(thainum)))
elif not isthainum and last_index + 1 == i and last_index != -1:
_flush(thainum, list_word_new)
thainum = []
list_word_new.append(word)
else:
Expand Down
33 changes: 33 additions & 0 deletions tests/core/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,39 @@ def test_number(self):
with self.assertRaises(TypeError):
text_to_thai_digit(None) # type: ignore[arg-type]

def test_text_to_num_zero(self):
# "ศูนย์" (zero) is excluded from the digit table as a special
# case, which used to corrupt or crash on any floating-point
self.assertEqual(
text_to_num("หนึ่งร้อยยี่สิบสี่จุดศูนย์สี่"), ["124.04"]
)
self.assertEqual(
text_to_num("หนึ่งร้อยยี่สิบเอ็ดจุดศูนย์สี่ห้า"), ["121.045"]
)
self.assertEqual(text_to_num("ศูนย์จุดศูนย์เก้า"), ["0.09"])
self.assertEqual(text_to_num("ห้าจุดศูนย์ศูนย์เก้า"), ["5.009"])
self.assertEqual(text_to_num("สามจุดสี่ศูนย์เก้าศูนย์"), ["3.409"])

# "ศูนย์" as part of an ordinary word (e.g. "center") must stay
self.assertEqual(
text_to_num("ศูนย์ประชุมอยู่ที่กรุงเทพ"),
["ศูนย์", "ประชุม", "อยู่", "ที่", "กรุงเทพ"],
)
self.assertEqual(
text_to_num("ค่าเช่าศูนย์ประชุมคือหนึ่งร้อยบาท"),
["ค่าเช่า", "ศูนย์", "ประชุม", "คือ", "100", "บาท"],
)

# "จุด" as an ordinary word (e.g. "point/spot") must not crash
self.assertEqual(
text_to_num("จุดศูนย์กลางของเมืองอยู่ที่นี่"),
["จุด", "ศูนย์กลาง", "ของ", "เมือง", "อยู่", "ที่นี่"],
)
self.assertEqual(
text_to_num("จุดศูนย์รวมของทุกคนคือที่นี่"),
["จุด", "ศูนย์รวม", "ของ", "ทุกคน", "คือ", "ที่นี่"],
)

# ### pythainlp.util.keyboard

def test_keyboard(self):
Expand Down