单词示例:
- 球
- 百科全书
- 画面
随机字符串示例:
- qxbogsac
- 杰盖尼
- rnnfdwpm
当然,随机字符串可能实际上是某种语言中的单词或看起来像一个单词。但基本上一个人能够说出它看起来“随机”与否,基本上只是通过检查你是否能够发音。
我试图计算熵来区分这两者,但它远非完美。你还有其他的想法,有效的算法吗?
但是有一个重要的要求,我不能使用重量级的库,比如nltk
字典。基本上我需要的是一些在大多数情况下都有效的简单快速的启发式方法。
单词示例:
随机字符串示例:
当然,随机字符串可能实际上是某种语言中的单词或看起来像一个单词。但基本上一个人能够说出它看起来“随机”与否,基本上只是通过检查你是否能够发音。
我试图计算熵来区分这两者,但它远非完美。你还有其他的想法,有效的算法吗?
但是有一个重要的要求,我不能使用重量级的库,比如nltk
字典。基本上我需要的是一些在大多数情况下都有效的简单快速的启发式方法。
我开发了一个名为Nosril的 Python 3 包,用于解决与 OP 要求密切相关的问题:确定在源代码挖掘期间提取的文本字符串是否是类/函数/变量/等。标识符或随机乱码。它不使用字典,但它确实包含了一个相当大的 n-gram 频率表,以支持其对文本字符串的概率评估。(我不确定这是否符合“字典”的条件。)该方法不检查发音,并且它的专业化可能使其不适合一般的单词/非单词检测;不过,也许它对 OP 或其他希望解决类似问题的人有用。
示例:以下代码,
from nostril import nonsense
real_test = ['bunchofwords', 'getint', 'xywinlist', 'ioFlXFndrInfo',
'DMEcalPreshowerDigis', 'httpredaksikatakamiwordpresscom']
junk_test = ['faiwtlwexu', 'asfgtqwafazfyiur', 'zxcvbnmlkjhgfdsaqwerty']
for s in real_test + junk_test:
print('{}: {}'.format(s, 'nonsense' if nonsense(s) else 'real'))
将产生以下输出:
bunchofwords: real
getint: real
xywinlist: real
ioFlXFndrInfo: real
DMEcalPreshowerDigis: real
httpredaksikatakamiwordpresscom: real
faiwtlwexu: nonsense
asfgtqwafazfyiur: nonsense
zxcvbnmlkjhgfdsaqwerty: nonsense
如果你真的是说你的随机性指标是发音,那么你就进入了语音学的领域:一种语言中允许的声音序列。正如@ChrisPosser 在他对您的问题的评论中指出的那样,这些允许的声音序列是特定于语言的。
这个问题仅在特定语言中才有意义。
无论您选择哪种语言,您都可以通过字母本身训练的 n-gram 模型获得一些运气(而不是单词,这是通常的方法)。然后,您可以计算特定字符串的分数,并设置一个阈值,在该阈值下,字符串是随机的,在该阈值下,字符串类似于单词。
编辑:有人已经这样做并实际实现了它:https ://stackoverflow.com/a/6298193/583834
警告我不是自然语言专家
假设链接中提到的内容If You Can Raed Tihs, You Msut Be Raelly Smrat是真实的,一个简单的方法是
创建单词的python dict,键作为字典中单词的第一个和最后一个字符
words = defaultdict()
with open("your_dict.txt") as fin:
for word in fin:
words[word[0]+word[-1]].append(word)
现在对于任何给定的单词,搜索字典(记住键是单词的第一个和最后一个字符)
for matches in words[needle[0] + needle[-1]]:
比较字典值中的字符是否与您的针匹配
for match in words[needle[0] + needle[-1]]:
if sorted(match) == sorted(needle):
print "Human Readable Word"
一个相对较慢的方法是使用difflib.get_close_matches(word,可能性[, n][, cutoff])
对我来说效果很好:
VOWELS = "aeiou"
PHONES = ['sh', 'ch', 'ph', 'sz', 'cz', 'sch', 'rz', 'dz']
def isWord(word):
if word:
consecutiveVowels = 0
consecutiveConsonents = 0
for idx, letter in enumerate(word.lower()):
vowel = True if letter in VOWELS else False
if idx:
prev = word[idx-1]
prevVowel = True if prev in VOWELS else False
if not vowel and letter == 'y' and not prevVowel:
vowel = True
if prevVowel != vowel:
consecutiveVowels = 0
consecutiveConsonents = 0
if vowel:
consecutiveVowels += 1
else:
consecutiveConsonents +=1
if consecutiveVowels >= 3 or consecutiveConsonents > 3:
return False
if consecutiveConsonents == 3:
subStr = word[idx-2:idx+1]
if any(phone in subStr for phone in PHONES):
consecutiveConsonents -= 1
continue
return False
return True
我编写了这个逻辑来检测字符串中连续元音和辅音的数量。您可以根据语言选择阈值。
def get_num_vowel_bunches(txt,num_consq = 3):
len_txt = len(txt)
num_viol = 0
if len_txt >=num_consq:
pos_iter = re.finditer('[aeiou]',txt)
pos_mat = np.zeros((num_consq,len_txt),dtype=int)
for idx in pos_iter:
pos_mat[0,idx.span()[0]] = 1
for i in np.arange(1,num_consq):
pos_mat[i,0:-1] = pos_mat[i-1,1:]
sum_vec = np.sum(pos_mat,axis=0)
num_viol = sum(sum_vec == num_consq)
return num_viol
def get_num_consonent_bunches(txt,num_consq = 3):
len_txt = len(txt)
num_viol = 0
if len_txt >=num_consq:
pos_iter = re.finditer('[bcdfghjklmnpqrstvwxz]',txt)
pos_mat = np.zeros((num_consq,len_txt),dtype=int)
for idx in pos_iter:
pos_mat[0,idx.span()[0]] = 1
for i in np.arange(1,num_consq):
pos_mat[i,0:-1] = pos_mat[i-1,1:]
sum_vec = np.sum(pos_mat,axis=0)
num_viol = sum(sum_vec == num_consq)
return num_viol
使用 PyDictionary。您可以使用以下命令安装 PyDictionary。
easy_install -U PyDictionary
现在在代码中:
from PyDictionary import PyDictionary
dictionary=PyDictionary()
a = ['ball', 'asdfg']
for item in a:
x = dictionary.meaning(item)
if x==None:
print item + ': Not a valid word'
else:
print item + ': Valid'
据我所知,您可以将 PyDictionary 用于其他一些语言,然后是英语。