for 循环的替代品 |如何检查单词是否包含不同单词的一部分

Alternative to for loops | How to check if word contains part of a different word

如果你检查下面的代码,我使用循环来检查一组单词中是否有一个单词是另一个单词的后缀。

我的问题是,如何替换双 for 循环?写这个任务的人提到有一个使用算法的解决方案(不知道那是什么:/)

def checkio(words):
    if len(words) == 1: return False
    else:
        for w1 in words:
            for w2 in words:
                if w1 == w2:
                    continue
                elif w1.endswith(w2) or w2.endswith(w1): return True
                else: return False

print checkio({"abc","cba","ba","a","c"}) # prints True in Komodo 
print checkio({"walk", "duckwalk"}) # prints True

第二个问题: 看来当前功能并不适用于所有环境。 有人可以指出我做错了什么吗?它适用于我的 Komodo IDE 但不适用于 chekio 网站。

这里有一个 link 任务:http://www.checkio.org/mission/end-of-other/

Python 的 str.endswith() 会完成这项工作。

示例脚本:

>>> a = 'hello'
>>> a.endswith('llo')
True
>>> a.endswith('ello')
True
>>> a.endswith('o')
True
>>> a.endswith('lo')
True
>>> a.endswith('ell')
False

包装到一个函数:

import itertools
def checkio(words):

    words = [ w for w, s in itertools.product(words, words) if w != s and ( w.endswith(s) or s.endswith(w) ) ]
    return False if len(words) == 0 else True

示例输出: You can test it here:

checkio( {"hello", "lo", "he"} ) => True
checkio( {"hello", "la", "hellow", "cow"} ) => False
checkio( {"walk", "duckwalk"} ) => True
checkio( {"one"} ) => False
checkio( {"helicopter", "li", "he"} ) => False

让Python生成所有要检查的组合:

import itertools

def checkio(data):
    return any((x.endswith(y) or y.endswith(x)) for x, y in itertools.combinations(data, 2))

让Python测试一下:

assert checkio({"abc","cba","ba","a","c"}) == True
assert checkio({"walk", "duckwalk"}) == True
assert checkio({"aaa", "bbb"}) == False

可以使用交集和理解:

def checkio(words):
    for w in words:
        ends = {w[i:] for i in range(1,len(w))}
        if len(words & ends) > 0:
            return True
    return False

输出:

>>> checkio({"walk", "duckwalk"})
True
>>> checkio({"walk", "duckbill"})
False

其工作方式如下。假设 words 包含单词 'scared'。当 w 为 'scared' 时,切片集 ends 变为 {'cared'、'ared'、'red'、'e'、'd'}。 & 是 Python 的交集运算符。如果任何单词对于 wordsends 都是通用的,例如'red',这个交集将是非空的,因此 len(words & ends) > 0 将是 True —— 然后作为函数值返回。如果代码成功循环遍历所有单词而没有遇到 len(words & ends) > 0,列表中没有一个单词作为另一个单词后缀的示例,因此返回 False

这是使用 itertools.combinations() 的 for 循环版本:

def checkio(words):
    for w1, w2 in itertools.combinations(words, 2):
        if w1.endswith(w2) or w2.endswith(w1):
            return True
    return False

print checkio({"abc","cba","ba","a","c"}) # prints True in Komodo only :/
print checkio({"walk", "duckwalk"}) # prints True
print checkio({"a", "foo", "bar"}) # prints False

给予:

True
True
False

如果您打印每次迭代,您将看到 combinations() 函数的工作原理,因此对于最后一个示例,您将看到它尝试以下操作:

a - foo
a - bar
foo - bar

谢谢大家,你们所有的评论和回复帮助我以不同的方式看待它。我认为这段代码不那么笨重和清晰,不需要模块导入

def checkio(words):
    for w1 in words:
        for w2 in words:
            if w1 != w2 and (w1.endswith(w2) or w2.endswith(w1)):
                return True
    return False