【问题标题】:How do I search substrings recursively in Python?如何在 Python 中递归搜索子字符串?
【发布时间】:2017-09-21 15:54:11
【问题描述】:

提前感谢您的帮助。

我有一个字符串列表

full_name_list = ["hello all","cat for all","dog for all","cat dog","hello cat","cat hello"]

我需要在每个元素与列表中的所有元素之间进行百分比匹配。例如,我需要首先将"hello all" 分解为["hello", "all"],我可以看到"hello""hello cat" 中,因此匹配率为50%。这是我到目前为止所拥有的,

    hello all   [u'hello', u'hello all', u'hello cat', u'cat hello'] [u'all', u'hello all', u'cat for all', u'dog for all'] 
    cat for all [u'cat', u'cat for all', u'cat dog', u'hello cat', u'cat hello']    [u'for', u'cat for all', u'dog for all']    [u'all', u'hello all', u'cat for all', u'dog for all']
    dog for all [u'dog', u'dog for all', u'cat dog']    [u'for', u'cat for all', u'dog for all']    [u'all', u'hello all', u'cat for all', u'dog for all']
    cat dog     [u'cat', u'cat for all', u'cat dog', u'hello cat', u'cat hello']    [u'dog', u'dog for all', u'cat dog']    
    hello cat   [u'hello', u'hello all', u'hello cat', u'cat hello']    [u'cat', u'cat for all', u'cat dog', u'hello cat', u'cat hello']    
    cat hello   [u'cat', u'cat for all', u'cat dog', u'hello cat', u'cat hello']    [u'hello', u'hello all', u'hello cat', u'cat hello']    

如您所见,每个子列表中的第一个单词包含正在搜索的子字符串,然后是包含该子字符串的元素。我能够为一个单词匹配做到这一点,并且我意识到我可以通过简单地通过单个单词之间的交集来获得双重匹配来继续这个过程,例如

    cat for all [(cat,for)  [u'cat for all']]   [(for,all)  [u'cat for all', u'dog for all']]

我遇到的问题是递归执行此操作,因为我不知道最长的字符串将有多长。另外,有没有更好的方法来做这个字符串搜索?最终我想找到匹配 100% 的字符串,因为实际上是"hello cat" == "cat hello"。我还想找到 50% 的匹配项等等。

我得到的一个想法是使用二叉树,但我该如何在 python 中执行此操作?到目前为止,这是我的代码:

logical_list = []
logical_list_2 = []
logical_list_3 = []
logical_list_4 = []
match_1 = []
match_2 = []
i = 0

logical_name_full = logical_df['Logical'].tolist()
for x in logical_name_full:
    logical_sublist = [x]+x.split()
    logical_list.append(logical_sublist)



for sublist in logical_list:
    logical_list_2.append(sublist[0])
    for split_words in  sublist[1:]:
        match_1.append(split_words)
        for logical_names in logical_name_full:
            if split_words in logical_names:
                match_1.append(logical_names)
        logical_list_2.append(match_1)
        match_1 = []
    logical_list_3.append(logical_list_2)
    logical_list_2 = []

【问题讨论】:

    标签: python recursion binary-search-tree


    【解决方案1】:

    我想我知道您要什么(如果不知道,请评论我的答案,我会尽力提供帮助)。我编写了一个小程序,可以满足您的要求:

    full_name_list = ["hello all","cat for all","dog for all","cat dog","hello cat","cat hello"]
    
    for i in range(len(full_name_list)):
        full_name_list[i] = full_name_list[i].split(' ')
    
    def match(i, j):
        word = full_name_list[i][j]
    
        for fullname in full_name_list:
            if full_name_list.index(fullname) == i: continue
    
            for name in fullname:
                if word == name:
                    fullname_str = fullname[0]
    
                    for i in range(1,len(fullname)):
                        fullname_str += ' ' + fullname[i]
    
                    return '"{}" is a {}% match to "{}"'.format(name, int(100/len(fullname)), fullname_str)
    
    print(match(0,1))
    

    您输入了两个参数,i 用于列表中名称的索引,j 用于全名中名称的索引。然后它返回函数与名称匹配的字符串,以及它的匹配程度。它还避免将单词与自身匹配。我在底部运行了一次该功能。它在hello all 中找到单词all 的匹配项,并成功。

    再一次,如果我回答得不好,请告诉我。它只返回找到的第一个匹配项,但可以轻松修改为返回所有匹配项。

    【讨论】:

    • 这正是我所需要的,但我需要一些额外的部分,1.我必须遍历 full_name_list 中的每个组件才能获得匹配百分比 2.如果字符串有多个单词,我需要它查找单个单词匹配和多个单词匹配,例如在示例中,我们搜索“all”,但我还需要搜索“hello”和“hello all” 3. 我需要返回至少有一个匹配项的所有单词
    【解决方案2】:

    如果我正确理解了这个问题,你有一个字符串列表,并且你想在所述字符串中找到一个单词的匹配百分比,百分比由字符串的多少个单词决定,从总数中词,是说的词。如果是这样,这个代码示例应该足够了:

    for i in full_name_list:
        if word in i.split(" "):
            total_words = len(i.split(" "))
            match_words = 0
            for w in i.split(" "):
                if word == w:
                    match_words += 1
            print(i + " Word match: " + str((match_words/total_words)*100) + "%")
    

    对于匹配多单词字符串,匹配字符串中单词的顺序并不重要: word = "测试字符串" full_name_list = ["test something", "test string something", "test string", "string test", "string something test"] 结果 = []

    for i in full_name_list:
        if len([item for item in word if item in i]) > 0:
            total_words = len(i.split(" "))
            match_words = 0.0
            for single_word in word.split(" "):
                for w in i.split(" "):
                    if single_word == w:
                        match_words += 1
            results.append(i + "," + str((match_words/total_words)*100) + "%")
    
    with open("file.csv", "w") as f:
        for i in results:
            f.write(i+"\n")
    

    【讨论】:

    • 这很酷,我只需要弄清楚如何使用列表中的每个单词来代替变量“word”,然后将其全部打印到 excel 中,这样我就可以看到所有百分比匹配。谢谢你给了我这个想法的另一种观点,因为我不需要遍历完整单词的每个组成部分并将它们与其他完整单词一一匹配,而是可以看到每个完整单词与其他完整单词的关系。
    • @EdwardMordechay 您可以将您的数组和 .join(" ") 放入单词变量中。
    • @EdwardMordechay 为了可视化到 excel,您可以只使用 csv。在这种情况下,您的 results.append 文件将如下所示: results.append(i + "," + str((match_words/total_words)*100) + "%") 之后您需要一些文件 IO。跨度>
    【解决方案3】:

    我进行了您要求的更改。如您所知,我使用了从here 获得的子集函数,它从itertools(内置于python)导入。如果这是一个问题,请通知我。

    这是新代码。我在底部运行它,以便您可以看到它在运行中的样子。您将索引i 输入到matches 函数中,其中ifull_name_list 中名称的索引。我相信这就是您所要求的一切。

    from itertools import chain, combinations
    
    full_name_list = ["hello all","cat for all","dog for all","cat dog","hello cat","cat hello"]
    
    for i in range(len(full_name_list)):
        full_name_list[i] = full_name_list[i].split(' ')
    
    def powerset(iterable):
        s = list(iterable)
        return list(chain.from_iterable(combinations(s, r) for r in range(1, len(s)+1)))
    
    
    def subset(string, container):  
        if string not in powerset(container): return False
    
        return True
    
    def makestring(names):
        fullname_str = names[0]
    
        for i in range(1,len(names)):
            fullname_str += ' ' + names[i]
    
        return fullname_str
    
    def matches(i):
        results = []
    
        fullname = full_name_list[i]
        fullnamePS = powerset(fullname)
    
        for fullname in full_name_list:
            if full_name_list.index(fullname) == i: continue
    
            for names in fullnamePS:
                if subset(names, fullname): 
    
                    results.append((int(100 * len(names)/len(fullname)), makestring(names), makestring(fullname)))
    
        return results
    
    for result in matches(1):
        print('"{}" is a {}% match to "{}"'.format(result[1],result[0],result[2]))
    

    【讨论】:

      猜你喜欢
      • 2023-04-02
      • 2012-06-25
      • 2015-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-30
      • 1970-01-01
      相关资源
      最近更新 更多