Python!根据与列表中单词的最大距离查找对

Python! Finding pairs depending on maximum distance from words in list

我正在编写一个程序来分析文本文件中的单词。我已经能够解析文本文件中的所有单词,并在执行繁琐的代码后将它们附加到列表中。我现在在这段代码中碰到了一个问题。我现在应该找到不超过索引中最大距离的词对(对于每个词)。 这是我能够获得的输入和字符串列表:

dist_max = int(input('Enter the maximum distance between words ==> '))

list_for_pairs = ['station', 'apple', 'chivalry', 'mansion', 'bear', \
                  'website', 'vest', 'amazing', 'mansion', 'apple', 'card', \
                  'station', 'card', 'book', 'same', 'tree', 'honor', \
                  'leaf', 'trace', 'tractor', 'bucket', 'bread', 'pears', 'book', \
                  'tractor', 'mouse', 'mansion', 'scratch', 'matter', 'trace']

在这种情况下,最大距离应为 2,例如,对于列表中的单词 'amazing','amazing' 应配对的对将是 'website'、'vest'、'mansion' 和 'apple'。这是因为最大距离为 2,并且列表中的所有单词都在该范围内。 这也是一个示例输出。

配对必须按字母顺序排列,只出现前 5 个和后 5 个,但应该说明总共有多少对。 最后我的代码:

pair_list = []
for i in range(len(list_for_pairs)+1):
    range_pos = int(range(0, dist_max)) # This is the range for the maximum distance
    # between words in the positive (+) direction
    range_neg = int(range(0, dist_max, -1))# This is the range for the maximum distance
    # between words in the negative (-) direction
    pair_list.append('({} {})'.format(list_for_pairs[i], list_for_pairs[range_pos]))
    pair_list.append('({} {})'.format(list_for_pairs[i], list_for_pairs[range_neg]))

不多,但基本上,我想做一个列表来放入所有的对,这将使长度部分更容易,而且我需要确保如果最大距离是我不添加任何东西超出列表范围。感谢任何提示,提前致谢!

使用:

pair_list = []
for i in range(len(list_for_pairs)):
   if i > 0:
        for j in range(max(0, i - 2)):
             pair_list.append('({} {})'.format(list_for_pairs[i], list_for_pairs[j]))
   if i < len(list_for_pairs) - 1):
        for j in range(i + 1, min(len(list_for_pairs), i + 2)):
             pair_list.append('({} {})'.format(list_for_pairs[i], list_for_pairs[range_neg]))

对于每个 i,j 从 1.i - 2 到 i-1 和 2.i + 1 到 i + 2(如果存在)。

您可以有一个嵌套的 for 循环,它是当前索引加上和减去 dist_max 的偏移量。然后确保偏移量不为 0 并且在范围内。

pair_list = []
for i, word in enumerate(list_for_pairs):
    for offset in range(-dist_max, dist_max+1):
        if offset and 0 <= i + offset < len(list_for_pairs): # Ignore when offset is 0 or would be out of bounds
            otherword = list_for_pairs[i + offset]
            pair_list.append((word, otherword))

print(pair_list)

这构建了整个对列表。请注意,我使用 set 来消除重复项。


pairs = set()
for i in range(len(list_for_pairs)):
    for j in range(-dist_max,dist_max+1):
        if not j:
            continue
        if 0 <= i+j < len(list_for_pairs):
            w1, w2 = list_for_pairs[i], list_for_pairs[i+j]
            if w1 > w2:
                w2,w1 = w1,w2
            pairs.add( (w1,w2) )
pairs = sorted(list(pairs))
#print(pairs)
print(len(pairs), "distinct pairs")
for i in range(5):
    print( pairs[i][0], pairs[i][1])
print("...")
for i in range(-5,0):
    print( pairs[i][0], pairs[i][1])

输出:

C:\tmp>python x.py  
Enter the maximum distance between words ==> 2
54 distinct pairs   
apples bakery       
apples basket       
apples bike         
apples truck        
bakery basket       
...                 
puppy weather       
safety vest         
scratch trash       
track truck         
vest whistle        
                    
C:\tmp>             

您不需要在前后搜索,因为这些对是按字母顺序添加的,与顺序无关。在下面复制的列表中,请注意不需要分析 'weather + challenge''challenge + weather' 两次。

list_for_pairs = ['weather', 'puppy', 'challenge', 'house', 'whistle', \
                  'nation', 'vest', 'safety', 'house', 'puppy', 'card', \
                  'weather', 'card', 'bike', 'equality', 'justice', 'pride', \
                  'orange', 'track', 'truck', 'basket', 'bakery', 'apples', 'bike', \
                  'truck', 'horse', 'house', 'scratch', 'matter', 'trash']
dist_max = 2

如果您的列表不包含重复项,则不需要集合来避免重复。您需要做的就是不要添加重复项!一个简单的实现如下所示:

pairs = []
for i in range(dist_max, len(list_for_pairs)):
    for j in range(i - dist_max, i):
        pair = list_for_pairs[i], list_for_pairs[j]
        if pair[1] < pair[0]:
            pair = pair[::-1]
        pairs.append(pair)
pairs.sort()

这非常适合列表理解,特别是如果您使用 sorted 而不是手动交换对:

pairs = sorted(sorted([list_for_pairs[i], list_for_pairs[j]]) 
         for i in range(dist_max, len(list_for_pairs)) for j in range(i - dist_max, i))

您可以将 [list_for_pairs[i], list_for_pairs[j]] 替换为 list_for_pairs[j:i+1:i-j]。在我看来,它看起来更漂亮,但我不确定这样做还有什么其他好处:

pairs = sorted(sorted(list_for_pairs[j:i+1:i-j]) for i in range(dist_max, len(list_for_pairs)) for j in range(i - dist_max, i))

由于实际上您的列表 确实 包含重复项,您可以使用 set 来汇总结果。由于集合是无序的,可以在事后对其进行排序:

pairs = sorted(set(sorted(list_for_pairs[j:i+1:i-j])
               for i in range(dist_max, len(list_for_pairs)) for j in range(i - dist_max, i)))

作为一个有趣的推论,您还可以在列表排序后使用 itertools.groupby 删除重复项:

pairs = sorted(sorted(list_for_pairs[j:i+1:i-j])
               for i in range(dist_max, len(list_for_pairs)) for j in range(i - dist_max, i))
pairs = [k for k, g in groupby(pairs)]

请注意,您也可以将最后一个写成一行,但我认为它太长了,不易读懂。