2014-07-02 8 views
5

Często muszę wykonywać porównania wartości Data.Text z różnymi wymaganiami dotyczącymi rozróżniania wielkości liter - często pojawia się, gdy używam chatter dla zadań NLP.Porównywanie wielkości liter/niewrażliwych na dane w Data.Text?

Na przykład podczas wyszukiwania tokenów do zadań związanych z wyodrębnianiem informacji, często muszę szukać w oparciu o relacje równości, które są mniej restrykcyjne niż standardowa równość łańcuchów. Rozróżnianie wielkości liter jest najczęstszą z tych zmian, ale często jest to funkcja określonego tokenu. Określenie takie jak "aktywuj" może zwykle być małe, ale jeśli jest to pierwsze słowo w zdaniu, zaczyna się od kapitału wiodącego, lub jeśli użyte w tekście tytułu może być we wszystkich wersjach lub napisane wielką literą w połowie zdania, więc porównania, które ignorują sprawę, mają sens. Odwrotnie, akronim (np. "US") ma inną semantykę w zależności od wielkości liter.

To wszystko, że nie mogę łatwo stworzyć opakowania typu "klasa" dla każdej klasy równości, ponieważ jest to aspekt oparty na wartości. (więc pakiet case-insensitive nie wygląda tak, jakby działał).

tej pory używam toLower aby kanoniczną reprezentację, i porównując te reprezentacje, więc mogę tworzyć niestandardowe wersje funkcji porównawczych Tekst które mają flagę czułości, np

matches :: CaseSensitive -> Text -> Text -> Bool 
matches Sensitive x y = x == y 
matches Insensitive x y = (T.toLower x) == (T.toLower y) 

Jednak ja Jestem zaniepokojony, że to wymaga dodatkowych wpadek w tekście wejściowym. Mogę sobie wyobrazić, że w niektórych przypadkach to się łączy, ale prawdopodobnie nie wszystkie (np .: T.isSuffixOf, T.isInfixOf).

Czy jest lepszy sposób to zrobić?

+5

Powinieneś naprawdę używać 'toCaseFold' zamiast' toLower' dla porównań wielkości liter. Może to nie ma większego znaczenia, gdy wiesz na pewno, że cały tekst będzie angielski, ale nadal dobrym nawykiem jest stosowanie bardziej ogólnego podejścia. – Carl

+0

Prawdopodobnie mógłbyś użyć funkcji najwyższego poziomu 'isCaseSensitive', być może używając' Data.Set' z wrażliwych na wielkość liter słów (w tym "US", ale nie "Us" lub "nas") i napisać test równości który mówi 'mecze xy | isCaseSensitive x || isCaseSensitive y = x == y' i '| inaczej = toCaseFold x == doCaseFold y' – AndrewC

Odpowiedz

2

Jeśli styl porównania jest kierowany przez semantykę porównywalnego przedmiotu, czy przekazanie tej semantyki z faktycznym tekstem ma sens? Można również normalizować następnie w razie potrzeby, aby uniknąć powtarzających się przechodzi później:

data Token = Token CaseSensitive Text -- Text is all lower-case if Insensitive 
    deriving Eq 

a może zdefiniować inteligentnego konstruktora:

token Sensitive t = Token Sensitive t 
token Insensitive t = Token Insensitive (T.toLower t) 

Oznacza to, że akronim „US” nie będzie kiedykolwiek porównać równa słowo "my", ale i tak wydaje się to logiczne.

Możesz także oznaczyć wartości bardziej szczegółowymi, takimi jak akronim/słowo/..., a nie tylko Sensitive/Insensitive.