正则表达式字典[Google类型搜索和正则表达式匹配]

时间:2013-04-21 20:40:05

标签: python regex search dictionary full-text-search

编辑: 以下代码的主要问题之一是将正则表达式对象存储在词典中,以及如何访问它们以查看它们是否可以匹配另一个串。但我仍然会留下我之前的问题,因为我认为可能有一种简单的方法来完成所有这些。

我想在python中找到一个方法,它知道如何返回两个字符串是否指向同一个东西的布尔值。我知道这很难,如果不是完全荒谬的编程,但我正在研究使用替代字符串的字典来处理这个问题,这些字典引用相同的东西。

以下是一些例子,因为我知道如果没有它们,这并没有多大意义。

如果我给出字符串:

'breakingBad.Season+01 Episode..02'

然后我希望它匹配字符串:

'Breaking Bad S01E02'

'three.BuCkets+of H2O'可以匹配'3 buckets of water'

我知道关于'3''water'等同义词几乎是不可能的,但我愿意将这些作为相关正则表达式同义词的词典提供给函数,如果需要的话

我觉得在python中有一个很多更简单的方法可以做到这一点,但总是如此,但这是我到目前为止所做的:

import re

def check_if_match(given_string, string_to_match, alternative_dictionary):
    print 'matching: ', given_string, '  against: ', string_to_match
    # split the string into it's parts with pretty much any special character 
    list_of_given_strings = re.split(' |\+|\.|;|,|\*|\n', given_string)
    print 'List of words retrieved from given string: '
    print list_of_given_strings
    check = False
    counter = 0
    for i in range(len(list_of_given_strings)):
        m = re.search(list_of_given_strings[i], string_to_match, re.IGNORECASE)
        m_alt = None
        try:
            m_alt = re.search(alternative_dictionary[list_of_given_strings[i]], string_to_match, re.IGNORECASE)
        except KeyError:
            pass
        if m or m_alt:
            if counter == len(list_of_given_strings)-1: check = True
            else: counter += 1
            print list_of_given_strings[i], ' found to match'
        else:
            print list_of_given_strings[i], ' did not match'
            break
    return check

string1 = 'breaking Bad.Season+01 Episode..02'
other_string_to_check = 'Breaking.Bad.S01+E01'
# make a dictionary of synonyms -  here we should be saying that "S01" is equivalent to "Season 01"
alternative_dict = {re.compile(r'S[0-9]',flags=re.IGNORECASE):re.compile(r'Season [0-9]',flags=re.IGNORECASE),\
                    re.compile(r'E[0-9]',flags=re.IGNORECASE):re.compile(r'Episode [0-9]',flags=re.IGNORECASE)}
print check_if_match(string1, other_string_to_check, alternative_dict)
print 
# another try
string2 = 'three.BuCkets+of H2O'
other_string_to_check2 = '3 buckets of water'
alternative_dict2 = {'H2O':'water', 'three':'3'}
print check_if_match(string2, other_string_to_check2, alternative_dict2)

返回:

matching:  breaking Bad.Season+01 Episode..02   against:  Breaking.Bad.S01+E01
List of words retrieved from given string: 
['breaking', 'Bad', 'Season', '01', 'Episode', '', '02']
breaking  found to match
Bad  found to match
Season  did not match
False

matching:  three.BuCkets+of H2O   against:  3 buckets of water
List of words retrieved from given string: 
['three', 'BuCkets', 'of', 'H2O']
three  found to match
BuCkets  found to match
of  found to match
H2O  found to match
True

我意识到这可能意味着我对字典键和值感到错误,但我觉得我正在远离一个可能已经创建的简单pythonic解决方案。

有人有任何想法吗?

1 个答案:

答案 0 :(得分:1)

我正在修补它并发现了一些有趣的事情:

  • 这可能与您将初始单词分解为列表的方式有关

    matching:  breaking Bad.Season 1.Episode.1   against:  Breaking.Bad.S1+E1
    List of words retrieved from given string:
    ['breaking', 'Bad', 'Season', '1', 'Episode', '1']
    
  • 我认为您希望它为..., 'Season 1', ...,而不是让'Season'1成为列表中的单独条目。

  • 您指定S[0-9],但这不会匹配两位数。

  • 你的正常表达存储在词典中是正确的;映射仅适用于一个方向。通过将r'Season [0-9]'映射到r'S[0-9]'而不是相反,我正在摆弄代码(遗憾的是不记得它是什么),它能够匹配Season

建议

  • 不是映射,而是为每个字符串类型(例如标题,季节,剧集)设置一个等价类,并为此设置一些匹配代码。
  • 分离解析并比较步骤。将每个字符串分别解析为通用格式或对象,然后进行比较
  • 您可能需要实现某种状态机才能知道您正在处理一个季节,并期望在它之后看到特定格式的数字。
  • 您可能希望使用第三方工具;我听说过有关Renamer
  • 的好消息