【问题标题】:Python! Finding pairs depending on maximum distance from words in listPython!根据与列表中单词的最大距离查找对
【发布时间】:2021-04-07 17:40:33
【问题描述】:

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

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 '和'苹果'。这是因为最大距离为 2,并且列表中的所有单词都在该范围内。 这也是一个示例输出。

这些对必须按字母顺序排列,只有第一个和最后 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]))

不多,但基本上,我想制作一个列表来放入所有对,这将使长度部分更容易,并且如果最大距离超出,我需要确保不添加任何内容列表范围。任何提示都表示赞赏,在此先感谢您!

【问题讨论】:

  • 这里还有一个你没有分享的细节,不是吗?每对中的单词必须按字母顺序排列。否则,whistle vest 将是最后一个条目。
  • 等一下,在我的代码上方。对不起,如果它到处都是。
  • 你是对的。我读错了。我很抱歉。
  • 您应该为帮助您的人投票,尤其是当您选择的答案可以解决您的问题时。
  • 我很抱歉,会的。

标签: python python-3.x string list range


【解决方案1】:

这构建了整个配对列表。请注意,我使用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>             

【讨论】:

  • 我不敢相信我没有想到这个系列,我在复制品上苦苦挣扎。代码通俗易懂,谢谢罗伯茨先生!
  • 如果你确定性地进行迭代,那就大材小用了。
  • 我不明白你的意思。
【解决方案2】:

用途:

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(如果存在)。

【讨论】:

    【解决方案3】:

    您可以有一个嵌套的 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)
    

    【讨论】:

      【解决方案4】:

      您无需在前后搜索,因为这些对是按字母顺序添加的,与顺序无关。在您的列表中,复制如下,请注意无需分析 '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)]
      

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

      【讨论】:

      • 我明白您的观点,我们不需要向前和向后搜索,但是由于列表包含重复项,您仍然有问题。你会从两个地方得到puppy / weatherhouse / puppy
      • @TimRoberts。感谢您指出了这一点。我没有注意到重复项。现已更新。
      猜你喜欢
      • 2021-09-19
      • 2021-07-07
      • 2021-01-14
      • 1970-01-01
      • 1970-01-01
      • 2020-10-03
      • 1970-01-01
      • 1970-01-01
      • 2012-06-11
      相关资源
      最近更新 更多