在字符串列表中寻找相邻项

3

我有一个列表和一个集合,我想在列表中查找集合中元素的所有出现次数,并获取单词左右的字符串。

我现在已经写好了以下内容:

unique_set = set(text)
context_key = {}
bad_counter = 0

for i,j in enumerate(unique_set):
    context_list = []
    if j in text:
        context = []
        context.append(text[i-1])
        context.append(text[i])
        context.append(text[i+1])
        if j in context:
            context_list.append(context)
            context_key[j] = context_list
        else:
            bad_counter += 1

print(bad_counter)
print(context_key)

这似乎实际上遍历了集合和列表,然而我把计数器放进去看它错过了多少值,但是它的总和并没有增加,因为完整文本列表的长度约为130k,15k个错误应该很糟糕,然而只有3个键值对让我感到困惑。这是输出:

15928
{'compost': [['gardens', 'compost', 'heaps']], 'extra': [['color', 'hair', 'extra']], 'commercial': [['commercial', 'first', 'came']]} 

最终目的是将集合中的唯一值作为字典键添加到context_key中,并将包含该值的任何列表作为context_key的字典值附加。
2个回答

2
如果你只是想制作一个单词列表,包括单词本身、前面的单词和后面的单词,则可以使用以下方法:
text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.".split(" ")

unique_set = set(text)
context_key = {}

for i,j in enumerate(unique_set):
    if i in (0, len(text)-1):
        continue

    indices = [i for i, x in enumerate(text) if x == j]

    contexts = []

    for index in indices:
        this_context = []

        word = j
        word_before = text[i-1]
        word_after = text[i+1]

        this_context.append(word_before)
        this_context.append(word)
        this_context.append(word_after)

        contexts.append(this_context)

    context_key[j] = contexts

print(context_key)

输出:

{'consectetur': [['Lorem', 'consectetur', 'dolor']], 'proident,': [['ipsum', 'proident,', 'sit']], 'quis': [['dolor', 'quis', 'amet,']], 'labore': [['sit', 'labore', 'consectetur']], 'esse': [['amet,', 'esse', 'adipiscing']], 'ex': [['consectetur', 'ex', 'elit,']], 'ea': [['adipiscing', 'ea', 'sed']], 'aliqua.': [['elit,', 'aliqua.', 'do']], 'aute': [['sed', 'aute', 'eiusmod']], 'reprehenderit': [['do', 'reprehenderit', 'tempor']], 'amet,': [['eiusmod', 'amet,', 'incididunt']], 'veniam,': [['tempor', 'veniam,', 'ut']], 'Duis': [['incididunt', 'Duis', 'labore']], 'pariatur.': [['ut', 'pariatur.', 'et']], 'est': [['labore', 'est', 'dolore']], 'commodo': [['et', 'commodo', 'magna']], 'id': [['dolore', 'id', 'aliqua.']], 'voluptate': [['magna', 'voluptate', 'Ut']], 'cupidatat': [['aliqua.', 'cupidatat', 'enim']], 'velit': [['Ut', 'velit', 'ad']], 'sit': [['enim', 'sit', 'minim']], 'elit,': [['ad', 'elit,', 'veniam,']], 'dolore': [['minim', 'dolore', 'quis'], ['minim', 'dolore', 'quis']], 'consequat.': [['veniam,', 'consequat.', 'nostrud']], 'cillum': [['quis', 'cillum', 'exercitation']], 'minim': [['nostrud', 'minim', 'ullamco']], 'exercitation': [['exercitation', 'exercitation', 'laboris']], 'magna': [['ullamco', 'magna', 'nisi']], 'sunt': [['laboris', 'sunt', 'ut']], 'sint': [['nisi', 'sint', 'aliquip']], 'eu': [['ut', 'eu', 'ex']], 'nulla': [['aliquip', 'nulla', 'ea']], 'laborum.': [['ex', 'laborum.', 'commodo']], 'nostrud': [['ea', 'nostrud', 'consequat.']], 'in': [['commodo', 'in', 'Duis'], ['commodo', 'in', 'Duis'], ['commodo', 'in', 'Duis']], 'incididunt': [['consequat.', 'incididunt', 'aute']], 'ut': [['Duis', 'ut', 'irure'], ['Duis', 'ut', 'irure']], 'culpa': [['aute', 'culpa', 'dolor']], 'mollit': [['irure', 'mollit', 'in']], 'laboris': [['dolor', 'laboris', 'reprehenderit']], 'ipsum': [['in', 'ipsum', 'in']], 'Lorem': [['reprehenderit', 'Lorem', 'voluptate']], 'Excepteur': [['in', 'Excepteur', 'velit']], 'deserunt': [['voluptate', 'deserunt', 'esse']], 'aliquip': [['velit', 'aliquip', 'cillum']], 'tempor': [['esse', 'tempor', 'dolore']], 'ullamco': [['cillum', 'ullamco', 'eu']], 'Ut': [['dolore', 'Ut', 'fugiat']], 'enim': [['eu', 'enim', 'nulla']], 'anim': [['fugiat', 'anim', 'pariatur.']], 'fugiat': [['nulla', 'fugiat', 'Excepteur']], 'irure': [['pariatur.', 'irure', 'sint']], 'occaecat': [['Excepteur', 'occaecat', 'occaecat']], 'nisi': [['sint', 'nisi', 'cupidatat']], 'officia': [['occaecat', 'officia', 'non']], 'dolor': [['cupidatat', 'dolor', 'proident,'], ['cupidatat', 'dolor', 'proident,']], 'non': [['non', 'non', 'sunt']], 'do': [['proident,', 'do', 'in']], 'et': [['sunt', 'et', 'culpa']], 'eiusmod': [['in', 'eiusmod', 'qui']], 'sed': [['culpa', 'sed', 'officia']], 'ad': [['qui', 'ad', 'deserunt']], 'adipiscing': [['officia', 'adipiscing', 'mollit']]}

编辑:

你提供的代码问题在于enumerate中的索引来自集合,这与它在文本中的索引不一定相同。这意味着你的单词并不总是出现在context中,因为该上下文中的单词按照你的集合中字母顺序排列,而不是按照text中单词列表的顺序排列。

希望这有些意义 :)


现在正在运行它,因为它是一个大文件,所以需要一点时间,但我已经用样本测试过了,它可以工作,所以我会将其标记为已回答,谢谢! - Sebastian Goslin
那么 if any(word) 可能是一个更好的解决方案,对吗? - Sebastian Goslin
我不太明白你的意思,但可能是... :) - Ed Ward

1

考虑到您声明的uniqueset只是从输入构建的set,事先构建它只会使代码进行更多不必要的迭代。我建议避免一开始就构建set,而是直接迭代检索到的值。

您可以通过调用其keys()方法从以下过程的输出字典中轻松检索相同的唯一数据。

此外,由于在Python中插入list的时间复杂度为O(n),因此我也建议避免使用它们。使用具有常量访问的数据结构如dict将使工作更快。

这是一个避免这些陷阱的解决方案。

def parse(input_file):

    with open(f'{input_file}', 'r') as f:
        data = f.read().split()

    size = len(data)
    indexes = dict()
    for i, x in enumerate(data):
        if x not in indexes:
            indexes[x] = dict()
        indexes[x][i] = (data[i-1]if i>0 else None, data[i+1]if i<size-2 else None)

    return indexes

我问了一个愚蠢的问题,但我想理解你的意思。在这种情况下,由于input_file已经是一个列表,我不是可以直接将其转换为集合而无需打开新文件吗? - Sebastian Goslin
1
我不愿意打开一个新文件的唯一原因是,输入来自多个负责预处理和其他测试的函数。 - Sebastian Goslin
1
我理解你的观点。打开input_file只是为了让我/你和其他人测试解决方案。你可以愉快地将其从那里删除,并将data作为函数参数。关于转换为set的部分,我认为它实际上涉及迭代所有元素。 - Giova
1
刚刚测试过,速度快了很多,只要 2 分钟,比之前的不到 0.5 秒快多了。 - Sebastian Goslin

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