文字列が名前の省略形であるかどうかを確認します
-
27-10-2019 - |
質問
文字列が別の単語の略語である可能性があるかどうかを確認するためのpythonアルゴリズムを開発しようとしています。例えば
fck
のための一致ですfc kopenhavn
それは単語の最初の文字と一致するからです。fhk
一致しないだろう。fco
一致すべきではありませんfc kopenhavn
誰もFCコペンハウンをfcoと略すことはないからである。irl
のための一致ですin real life
.ifk
のための一致ですifk goteborg
.aik
のための一致ですallmanna idrottskluben
.aid
のための一致ですallmanna idrottsklubben
.これは実際のチーム名の略語ではありませんが、スウェーデン語の略語がどのように形成されているかについてドメイン固有の知識を適用しない限り、それを除外するのは難しいと思います。manu
のための一致ですmanchester united
.
アルゴリズムの正確なルールを説明するのは難しいですが、私の例が私が何を求めているのかを示してくれることを願っています。
更新 一致する文字を大文字にして文字列を表示するのに間違いを犯しました。実際のシナリオでは、すべての文字が小文字であるため、どの文字が大文字になっているかを確認するだけでは簡単ではありません。
解決
これは私が作成したいくつかの余分なものを含むすべてのテストに合格します。再帰を使用します。ここに私が使用したルールがあります:
- 省略形の最初の文字は、省略形の最初の文字と一致する必要があります テキスト
残りの省略形(abbrevから最初の文字を引いたもの)は、以下の省略形でなければなりません:
- 残りの単語、または
- から始まる残りのテキスト 最初の単語の任意の位置。
tests=(
('fck','fc kopenhavn',True),
('fco','fc kopenhavn',False),
('irl','in real life',True),
('irnl','in real life',False),
('ifk','ifk gotebork',True),
('ifko','ifk gotebork',False),
('aik','allmanna idrottskluben',True),
('aid','allmanna idrottskluben',True),
('manu','manchester united',True),
('fz','faz zoo',True),
('fzz','faz zoo',True),
('fzzz','faz zoo',False),
)
def is_abbrev(abbrev, text):
abbrev=abbrev.lower()
text=text.lower()
words=text.split()
if not abbrev:
return True
if abbrev and not text:
return False
if abbrev[0]!=text[0]:
return False
else:
return (is_abbrev(abbrev[1:],' '.join(words[1:])) or
any(is_abbrev(abbrev[1:],text[i+1:])
for i in range(len(words[0]))))
for abbrev,text,answer in tests:
result=is_abbrev(abbrev,text)
print(abbrev,text,result,answer)
assert result==answer
他のヒント
あなたがやりたいと思うことを達成する方法は次のとおりです
import re
def is_abbrev(abbrev, text):
pattern = ".*".join(abbrev.lower())
return re.match("^" + pattern, text.lower()) is not None
キャレットは、略語の最初の文字が単語の最初の文字と一致することを確認します。
編集:あなたの新しい更新は、ルールを少し変更しました。を使用して "(|.*\s)"
の代わりに ".*"
略語の文字は、互いに隣接している場合、または次の文字が新しい単語の先頭に表示されている場合にのみ一致します。
これは正しく一致します fck
と FC Kopenhavn
, しかし、 fco
そうではありません。しかし、マッチング aik
と allmanna idrottskluben
ウィル ない 仕事、それはスウェーデン語の知識を必要とし、行うのは簡単ではありませんように。
マイナーな変更を加えた新しいコードは次のとおりです
import re
def is_abbrev(abbrev, text):
pattern = "(|.*\s)".join(abbrev.lower())
return re.match("^" + pattern, text.lower()) is not None
@Ocaso Protal
コメントで言った how should you decide that aik is valid, but aid is not valid?
そして彼は正しいです。
私の心に入ったアルゴは、で動作することです word threshold
(スペースで区切られた単語の数)。
words = string.strip().split()
if len(words) > 2:
#take first letter of every word
elif len(words) == 2:
#take two letters from first word and one letter from other
else:
#we have single word, take first three letter or as you like
あなたはあなたの論理を定義する必要があります、あなたは盲目的に略語を見つけることができません。
あなたのアルゴリズムは単純なようです-略語はすべての大文字の連結です。だから:
upper_case_letters = "QWERTYUIOPASDFGHJKLZXCVBNM"
abbrevation = ""
for letter in word_i_want_to_check:
if letter in letters:
abbrevation += letter
for abb in _list_of_abbrevations:
if abb=abbrevation:
great_success()
これで十分かもしれません。
def is_abbrevation(abbrevation, word):
lowword = word.lower()
lowabbr = abbrevation.lower()
for c in lowabbr:
if c not in lowword:
return False
return True
print is_abbrevation('fck', 'FC Kopenhavn')