Skip to content

internationalize word boundary checks#49

Open
aseifert wants to merge 27 commits into
vi3k6i5:masterfrom
aseifert:master
Open

internationalize word boundary checks#49
aseifert wants to merge 27 commits into
vi3k6i5:masterfrom
aseifert:master

Conversation

@aseifert

Copy link
Copy Markdown

Hi there,

I think the only safe way to deal with issue #48 would be to test against the \W class [1]. Judging from the benchmarks linked on https://github.com/vi3k6i5/flashtext#why-not-regex this seems to run slower by a factor of 1-2 though.

Best,
Alex

[1] Quoting the Python docs:

\b is defined as the boundary between a \w and a \W character (or vice versa), or between \w and the beginning/end of the string. This means that r'\bfoo\b' matches 'foo', 'foo.', '(foo)', 'bar foo baz' but not 'foobar' or 'foo3'.

vi3k6i5 and others added 27 commits November 10, 2017 20:47
added reference to flashtext paper
  `charactes` | `characters`
  `explaination` | `explanation`
  `matche` | `match`
Fix issue with incomplete keyword at the end of the sentence
@coveralls

Copy link
Copy Markdown

Coverage Status

Coverage increased (+0.7%) to 100.0% when pulling 9b6b187 on aseifert:master into 5591859 on vi3k6i5:master.

1 similar comment
@coveralls

coveralls commented Mar 19, 2018

Copy link
Copy Markdown

Coverage Status

Coverage increased (+0.7%) to 100.0% when pulling 9b6b187 on aseifert:master into 5591859 on vi3k6i5:master.

@ioistired

Copy link
Copy Markdown

Another way, based on https://stackoverflow.com/a/2998550:

def is_word_char(c, _categories=frozenset({'Ll', 'Lu', 'Lt', 'Lo', 'Lm', 'Nd', 'Pc'})):
    return unicodedata.category(c) in _categories

Comment thread flashtext/keyword.py
char = sentence[idx]
# when we reach a character that might denote word end
if char not in self.non_word_boundaries:
if KeywordProcessor.NON_WORD_CHAR_REGEX.match(char):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why the ugly direct reference to the class? just use self

@senpos

senpos commented Feb 21, 2020

Copy link
Copy Markdown

Another way to do it:

from functools import lru_cache

from flashtext import KeywordProcessor


class NonWordBoundaries:
    def __init__(self, *predicates):
        self.predicates = predicates

    @lru_cache(maxsize=128)
    def __contains__(self, ch):
        for predicate in self.predicates:
            if predicate(ch):
                return True
        return False


def main():
    words_to_search = ["рок"]

    keyword_processor = KeywordProcessor()
    keyword_processor.set_non_word_boundaries(NonWordBoundaries(str.isalpha, str.isdigit))
    keyword_processor.add_keywords_from_list(words_to_search)
    keywords_found = keyword_processor.extract_keywords('рок порок роковой')
    print(keywords_found)

Not sure about performance though. But at least it is easy to modify the behaviour.

@alexpeaceca

Copy link
Copy Markdown

Benchmarks vs. Regex are for the English only char set. Is increasing the word boundaries like this effecting flashtext performance in any significant way?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants