String 使用模式生成合理的字符串
我有一个字符串表(大约100000个),格式如下:String 使用模式生成合理的字符串,string,design-patterns,pattern-matching,String,Design Patterns,Pattern Matching,我有一个字符串表(大约100000个),格式如下: pattern , string e、 g- *l*ph*nt , elephant c*mp*t*r , computer s*v* , save s*nn] , sunny ]*rr] , worry 为了简化,假设a*表示元音,辅音保持不变,]表示“y”或“w”(例如,音韵学中的半元音/圆元音) 给定一个模式,生成可能的可感知字符串的最佳方法是什么?一个合理的字符串被定义为一个字符串,该字符串在数据集中具有其连续的两个字母子字符串中的
pattern , string
e、 g-
*l*ph*nt , elephant
c*mp*t*r , computer
s*v* , save
s*nn] , sunny
]*rr] , worry
为了简化,假设a*
表示元音,辅音保持不变,]
表示“y”或“w”(例如,音韵学中的半元音/圆元音)
给定一个模式,生成可能的可感知字符串的最佳方法是什么?一个合理的字符串被定义为一个字符串,该字符串在数据集中具有其连续的两个字母子字符串中的每一个,这些子字符串在模式中没有指定
e、 g-
*l*ph*nt , elephant
c*mp*t*r , computer
s*v* , save
s*nn] , sunny
]*rr] , worry
你好,你好,霍拉
“hallo”是合理的,因为“ha”、“al”、“lo”可以在数据集中看到,就像“have”、“alway”、“low”一样。不考虑这两个字母“ll”,因为它是在模式中指定的
有哪些简单有效的方法可以做到这一点?
是否有实现这一目标的库/框架
我没有特定的语言,但更喜欢在这个程序中使用java。由于两个字母子字符串的可能性不多,您可以遍历数据集并生成一个表,其中包含每两个字母子字符串的计数,因此该表将如下所示:
ee 1024 times
su 567 times
...
xy 45 times
xz 0 times
该表将很小,因为您只需要存储大约26*26=676个值
您只需对数据集执行一次此操作(如果数据集是动态的,则每次更改表时都要更新该表),并且可以使用该表评估可能的字符串。例如,在您的示例中,添加'ha'、'al'和'lo'的值以获得字符串'hallo'的“分数”。然后,选择得分最高的字符串
请注意,可以通过检查较长的子字符串(例如三个字母)来提高评分,但这也会导致较大的表。这特别适用于Pythonitertools、set和re操作:
import re
import itertools
VOWELS = 'aeiou'
SEMI_VOWELS = 'wy'
DATASET = '/usr/share/dict/words'
SENSIBLES = set()
def digraphs(word, digraph=r'..'):
'''
>>> digraphs('bar')
set(['ar', 'ba'])
'''
base = re.findall(digraph, word)
base.extend(re.findall(digraph, word[1:]))
return set(base)
def expand(pattern, wildcard, elements):
'''
>>> expand('h?', '?', 'aeiou')
['ha', 'he', 'hi', 'ho', 'hu']
'''
tokens = re.split(re.escape(wildcard), pattern)
results = set()
for perm in itertools.permutations(elements, len(tokens)):
results.add(''.join([l for p in zip(tokens, perm) for l in p][:-1]))
return sorted(results)
def enum(pattern):
not_sensible = digraphs(pattern, r'[^*\]]{2}')
for p in expand(pattern, '*', VOWELS):
for q in expand(p, ']', SEMI_VOWELS):
if (digraphs(q) - not_sensible).issubset(SENSIBLES):
print q
## Init the data-set (may be long...)
## you may want to pre-compute this
## and adapt it to your data-set.
for word in open(DATASET, 'r').readlines():
for digraph in digraphs(word.rstrip()):
SENSIBLES.add(digraph)
enum('*l*ph*nt')
enum('s*nn]')
enum('h*ll*')
谢谢你,施奈德。这道题中我的字母表不是英语,而是一个大得多的字母表。例如,它还包括重音字母。(像a,á,ã,å,å,ă,ą——更像是一个扩展的拉丁字母表——我使用的是Unicode)。我的目标是优化性能和最少的内存使用。无论如何,我将尝试看看子字符串表变得有多糟糕。您应该在前面提到字母表的大小,但是这个解决方案可以扩展。作为记录,它在1.6ms内产生60'*l*ph*nt',在0.5ms内产生20'*h*ll*(dict中有98569个单词)。这是一个很好的解决方案。花了一些时间来理解它(我对Python比较陌生)。这就是我一直在寻找的东西。谢谢你@fra。