用两个字母python进行线性搜索

问题描述

我有这个程序应该返回(使用线性搜索)“语料库”中紧跟在“last”之后的所有单个字符实例的列表(包括重复项)。字符应该与它们在语料库中出现的顺序相同

示例:

    filter_possible_chars('lazy languid line','la')
        ['z','n']
        filter_possible_chars('pitter patter batton','tt')
        ['e','e','o']
filter_possible_chars('pitter pattor batt','tt')
    ['e','o']

但是我的程序在第二个示例中遇到了问题,在单词 batt 中的第三个 tt 之后,它之后没有任何内容,因此显然不应将其他任何内容放入列表中,但我得到的 IndexError 列表索引超出了范围?

这是函数

def filter_possible_chars(corpus,last):

listo = []
last_list = []
final = []

for thing in corpus:
    listo.append(thing)
for last_word in last:
    last_list.append(last_word)
    
    
for index,letter in enumerate(listo):
    
    if letter == last_list[0]:
        if listo[index+1] == last_list[1]:
            final.append(listo[index+2])  
print(final)

解决方法

您似乎已经确定了问题;您有时会尝试访问索引超过列表最大索引的列表元素:final.append(listo[index+2]) 或此处 listo[index+1]

您可以定义一个辅助方法来首先检查访问是否成功。

def get(_list,index):
    if len(_list) >= index - 1:
        return _list[index]

my_list = [1,2,3]
idx = get(my_list,2) # 3
idx = get(my_list,4) # None
if idx is not None:
  # do stuff
,

您遇到的问题是 'tt' 位于您的第三个字符串的末尾,因此当您尝试查找此后的字母时,您增加了索引,但字符串已到达末尾,当试图将索引增加一,你最终会要求一个不存在的字符

首先,在这种情况下,如果您想让它返回字符串的第一个字符,请使用 modulus 运算符将值减少为零:

def filter_possible_chars(corpus,last):

    listo = []
    last_list = []
    final = []

    for thing in corpus:
        listo.append(thing)
    for last_word in last:
        last_list.append(last_word)


    for index,letter in enumerate(listo):

        if letter == last_list[0]:
            if listo[(index+1)%len(corpus)] == last_list[1]:
                final.append(listo[(index+2)%len(corpus)])
    print(final)

或者,如果你希望它在这种情况下返回 None,你可以添加一个 if 语句来检测它是否在它的极限,如果是,什么都不做,然后使用 {{ 1}}

,

好吧,试试这个,它解决了索引问题:

import re

query_list = [
['lazy languid line','la'],['pitter patter batton','tt'],['pitter pattor batt','tt']
]


def search(query):
    query_string = query[0]
    query_key = query[1]
    result = []
    for match in re.finditer(query_key,query_string):
        if match.span()[-1] < len(query_string):
            result.append(query_string[match.span()[-1]])
        else:
            result.append(None)
    return result

for query in query_list:
    result = search(query)
    print (query)
    print (result)

输出:

['lazy languid line','la']
['z','n']
['pitter patter batton','tt']
['e','e','o']
['pitter pattor batt','o',None]
,

它后面没有任何东西,所以显然不应该在列表中放任何其他东西

当代码到达倒数第二个 t 时,if 条件都为 True 并且它试图得到 listo[index+2] 什么都不是,所以它引发 IndexError 告诉你我没有'不知道你想让我得到什么。当涉及到最后一个 t 时,它再次发生,试图获得 listo[index+1]

您可以在倒数第三个字符处停止搜索:

def filter_possible_chars(corpus,last):
    result = []
    for i in range(len(corpus)-2):
        if corpus[i:i+2] == last:
            result.append(corpus[i+2])
    print(result)
,

你可以使用列表推导来做到这一点。

def filter_possible_chars(corpus,last):
    parts = [word.split(last) for word in corpus.split() if last in word]
    return [w[1][0] for w in parts if w[1]]

print (filter_possible_chars('lazy languid line','la'))
print (filter_possible_chars('pitter patter batton','tt'))
print (filter_possible_chars('pitter pattor batt','it'))
print (filter_possible_chars('pitter pattor batt','er'))
print (filter_possible_chars('pitter pattor batt','ox'))

您可以将这两行合并为一个长列表推导式,如下所示:

return [word.split(last)[1][0] for word in corpus.split() if last in word and word.split(last)[1]]

让我解释一下代码:

parts = [word.split(last) for word in corpus.split() if last in word]

这里我尝试使用

将语料库拆分为单个单词
for word in corpus.split()

之后,我检查 last 是否在单个单词中

如果子字符串 last 存在,那么我将再次使用 last 作为子字符串拆分单词。这将给出两组字符串。第一部分将是 last 中子字符串之前的所有字符,第二部分将是 last 中子字符串之后的所有字符。

例如,对于子字符串 lazy['','zy'] 将被拆分为 la。而对于pitter

['pi','er'] 将被拆分为tt

一旦你有了这个列表,那么你需要从索引 1 中选择第一个字符。

搜索la

lazy languid line 将导致 [['','zy'],['','nguid']]

搜索`tt':

pitter patter batton 将导致 [['pi','er'],['pa',['ba','on']]

搜索`tt':

pitter pattor batt 将导致 [['pi','or'],'']]

搜索`er':

pitter pattor batt 将导致 []

搜索`ox':

pitter pattor batt 将导致 []

这告诉我们,如果索引 1 值有一个字符串,我们可以选择所有结果。

所以下一个列表推导式语句是:

return [w[1][0] for w in parts if w[1]]

在这里,我们从 parts 中提取每个块并检查索引 1 是否包含任何字符串。如果是,则提取第 0 个位置并返回。

以下语句的输出是:

print (filter_possible_chars('lazy languid line','ox'))

['z','n']
['e','o']
['e','o']
['t']
[]
[]