如何从单词列表中创建正则表达式?

8
我有一个单词字典(实际上我有嵌套的动词变形字典,但这不是相关的),我想通过组合它们来创建一个正则表达式。
{
  'yo': 'hablaba',
  'tú': 'hablabas',
  'él': 'hablaba',
  'nosotros': 'hablábamos',
  'vosotros': 'hablabais',
  'ellos': 'hablaban',
  'vos': 'hablabas',
}

...如何制作:

'habl((aba(s|is|n)?)|ábamos)' # I think that's right

如果我不包括'hablábamos',那么很容易 - 它们都是相同的前缀,我可以得到:

'hablaba(s|is|n)?'

…但我想要一个普遍适用的表单,这可能吗?


1
你是想从字典中的值生成一个正则表达式吗?还是想编写一个正则表达式来验证字典中的值。或者完全是其他事情? - johnsyweb
2
我想要生成它。我的标签错了吗? - Malena Torres
有一个 JavaScript 库可以为您完成此操作:https://github.com/devongovett/regexgen(也许 Python 有类似的东西?) - kashiraja
2个回答

9

是的,我相信这是可能的。

为了帮助您入手,这是我如何分解这个问题。

通过找到与所有拒绝值的开头匹配的最长字符串来计算根:

>>> root = ''
>>> for c in hablar['yo']:
...     if all(v.startswith(root + c) for v in hablar.itervalues()):
...         root += c
...     else:
...        break
... 
>>> root
'habl'

剩下的单词制作出一个结尾的列表

>>> endings = [v[len(root):] for v in hablar.itervalues()]
>>> print endings
['abas', 'aba', 'abais', 'aba', '\xc3\xa1bamos', 'aban', 'abas']

您可能想要筛选出重复项:
>>> unique_endings = set(endings)
>>> print unique_endings
set(['abas', 'abais', '\xc3\xa1bamos', 'aban', 'aba'])

然后使用竖杠将这些结尾连接起来:
>>> conjoined_endings = '|'.join(unique_endings)
>>> print conjoined_endings
abas|abais|ábamos|aban|aba

形成正则表达式很简单,只需将根和连接后缀字符串用括号组合起来:

>>> final_regex = '{}({})'.format(root, conjoined_endings)
>>> print final_regex
habl(abas|abais|ábamos|aban|aba)

2
谢谢@Johnsyweb,是的,那很有帮助。但我不能给你点赞:(“需要15个声望”)。我应该接受你吗? - Malena Torres
@MalenaTorres:不用谢。希望这能让你开始,即使我的语言术语有误。我很好奇为什么你想要如此压缩正则表达式,因为你没有处理大量数据,更复杂的表达式只会增加验证时间。 - johnsyweb
1
我让我的示例比实际情况更简单,实际上它将像 {'yo': '\w+aba'} 这样。最后,我想将不规则动词与规则动词进行比较,以了解它们的规则,并且我将有另一个类似于 yo = {'imperfecto': '\w+aba', 'presente': '\w+o'} 的字典。对于不规则动词来说更加复杂,现在我只是开始尝试我的想法,看看我能做什么。 - Malena Torres

3

我认为你需要采用更简单的方法。

>>> x={
...   'yo': 'hablaba',
...   'tú': 'hablabas',
...   'él': 'hablaba',
...   'nosotros': 'hablábamos',
...   'vosotros': 'hablabais',
...   'ellos': 'hablaban',
...   'vos': 'hablabas',
... }
>>> x
{'t\xc3\xba': 'hablabas', 'yo': 'hablaba', 'vosotros': 'hablabais', '\xc3\xa9l': 'hablaba', 'nosotros': 'habl\xc3\xa1bamos', 'ellos': 'hablaban', 'vos': 'hablabas'}
>>> x.values
<built-in method values of dict object at 0x20e6490>
>>> x.values()
['hablabas', 'hablaba', 'hablabais', 'hablaba', 'habl\xc3\xa1bamos', 'hablaban', 'hablabas']
>>> "|".join(x.values())
'hablabas|hablaba|hablabais|hablaba|habl\xc3\xa1bamos|hablaban|hablabas'

如果你只是用交替运算符连接哈希值,那么它应该实现你想要的功能。

1
谢谢Vorsprung :) 但是我有很多单词和其他的变形(我给出的是不完美变位,还有大约15个),而且我不想使用太多空间。但是你的想法确实可行 :) - Malena Torres
1
我总是认为电脑内存比我的宝贵时间便宜 :) - Vorsprung
保持简单易懂确实有很多值得说的地方! - johnsyweb
@MalenaTorres:请在上面的原始问题陈述中添加那个激励细节。这会有所不同。另外,您真的想要具有最少字符的正则表达式吗?(还是只是一个相当优化的'|'分隔的连接列表,利用共享前缀?) - smci

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接