【问题标题】:Return True and stop if first item in list is matches, return false if no item matches如果列表中的第一个项目匹配,则返回 True 并停止,如果没有项目匹配,则返回 false
【发布时间】:2018-01-01 19:12:22
【问题描述】:

我写了一个函数来根据以下条件检查字符串:

  • 检查字符串中的任何单词是否在列表 1 中。
  • 如果字符串在列表 1 中,则返回位置以查看它旁边的项目是否在 该字符串在列表 2 中。
  • 如果在列表 1 和列表 2 中,则返回 True。
  • 否则返回 False。

棘手的部分是这些列表真的很长。因此,为了提高效率,列表 2 中的第一次出现将返回 True 并移动到下一个字符串。

以下是我扼杀的代码,但我怀疑它是否按预期工作。效率也是她的关键。我尝试创建列表 1 和列表 2 的完整组合,然后循环遍历,但每个字符串循环超过 1 亿次似乎有点疯狂。

第一个代码:

def double_loop(words):
    all_words = words.split()
    indices = [n for n,x in enumerate(allwords) if x in list1]
    if len(indices) != 0:
        for pos in indices[:-1]: 
            if all_words[pos+1] in list2: 
                return True 
#the purpose here is not to continue looking #through the whole list of indices, but end as soon as list2 contains an item 1 position after.
                    break
    else:
        return False

我不确定上面的代码是否根据我上面的逻辑工作。比较起来;

第二个代码:

def double_loop(words):
    all_words = words.split()
    indices = [n for n,x in enumerate(allwords) if x in list1]
    if len(indices) != 0:
        indices2 = [i for i in indices[:-1] if all_words[i+1] in list2]
        if len(indices2) != 0:
            return True
        else:
            return False
    else:
        return False

根据我的测试数据具有相同的运行时间。

我想更清楚的问题是,我的第一个代码是否会真正运行,直到找到符合其标准的“第一个”元素并中断。还是它仍然像第二个代码一样贯穿所有元素。

【问题讨论】:

  • “我怀疑它是否按预期工作”
  • 嗨,对不起,我应该更准确,运行时间很慢,我不知道这是否是适合我的目的的正确代码。
  • 这不能回答@timgeb 的问题。代码怎么没有按照你想要的方式工作?
  • 换句话说,你遇到了什么错误。
  • 并且您提供的代码无法运行:allwords vs all_words

标签: python loops


【解决方案1】:

如果我正确理解您的问题,那么您将使用预先计算的索引实现最快的查找时间。该索引是列表 1 的所有项的集合,其中以下项在列表 2 中。

# Build index, can be reused
index = set(item1 for i, item1 in enumerate(list1[:-1]) if list1[i+1] in list2)

def double_loop(words):
  return any(word in index for word in words.split())

无论 list1 和 list2 有多长,索引查找都将在恒定时间内完成。当 list1 和 list2 变得更长时,索引构建将花费更长的时间。请注意,当 list1 很大时,将 list2 设置为一个集合可能会加快索引构建速度。

【讨论】:

    【解决方案2】:

    您可以通过在单个列表理解中组合您的条件来仅迭代一次主列表:

    list1 = ['h', 'e', 'l', 'l', 'o']
    list2 = ['a', 'h', 'e', 'p', 'l', 'o']
    set_list2 = set(list2)
    
    check = [item for x, item in enumerate(list1) if item in set_list2 and list2[x+1] == item]
    

    如果你想让函数短路:

    def check(list1, list2):
        set_list2 = set(list2)
        for x, item in enumerate(list1):
            if item in set_list2 and list2[x+1] == item:
                return True
        return False
    
    a = check(list1, list2)
    

    【讨论】:

      【解决方案3】:

      首先,您的list1list2 不应该是列表,而是集合。这是因为集合查找是哈希查找,而列表查找是线性查找。

      而且你不需要嵌套循环。

      def single_loop(words):
          all_words = words.split()
          for w1, w2 in ((all_words[i],all_words[i+1]) for i in range(len(all_words)-1)):
              if w1 in set1 and w2 in set2:
                  return True
          else:
              return False
      

      【讨论】:

      • 当然,假设allwords 可以转换为集合是不安全的,也许list1
      • list1 和 2 是集合。解决了这个问题。为了提高效率,我试图避免查看 list1[i+1] 中的所有匹配项是否都在 list2 中。相反,当最左边的匹配项时,它会停止寻找匹配项。
      • 两点。即使对于非常大的集合,集合查找也很便宜。如果set1 测试成功,if w1 in set1 and w2 in set2 只会进行set2 成员资格测试。
      猜你喜欢
      • 2020-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-18
      • 2022-11-29
      • 2011-02-11
      • 1970-01-01
      相关资源
      最近更新 更多