检查String是否是列表中元素的串联

时间:2015-12-01 22:26:11

标签: python string

是否有一种优雅的方式(最好是pythonic)来检查String s 是否是set L 子集元素的串联? L 的元素可能会在 s 中出现多次。

例如:

L = set(["a", "ab", "c", "e"])

然后“abac”是 L

子集元素的有效串联

“aaaaaaa”也是有效的连接。

但“ad”不是因为“d”不在L中。

3 个答案:

答案 0 :(得分:5)

import re
L = ["no", "force", "in", "the", "verse", "can", "stop", "me"]
# make this: "(?:no|force|in|the|verse|can|stop|me)*$"
r = re.compile( "(?:" + "|".join(L) + ")*$")
r.match("shiny")  # -> None
r.match("canme")  # -> not None

适用于给定的字符串集。 re库中有一个函数可以引用字符串(转义|等),这样您就可以在运行时安全地创建这样的表达式。

r = re.compile( "(?:"  + "|".join( re.escape(s) for s in L) + ")*$" )

无论子串出现多少次,它都会匹配;如果某些字符串是其他字符串的前缀,则可能会出现奇怪的结果,等等。 它可能有令人讨厌的运行时。如果所有字符串在开头都很容易区分开来,那就不应该了。

答案 1 :(得分:2)

你可以尝试递归方法。

def isIn(s,L):
    if not s: #checks for empty string
        return True
    index = 1
    while index-1 < len(s):
        if s[0:index] in L and isIn(s[index:],L):
            return True
        index+=1
    return False

关于此的一些注释:

  • 这取决于python布尔运算符and是贪婪的事实(我很确定它是)。这意味着如果s[0:index] in L为假,那么它甚至不会评估下一个。为了安全起见,你可以做一个嵌套if(把if块中的递归调用)

  • s in set表达式的平均运行时间为O(1),因此请确保L IS实际上是一个集合,否则s in list是平均值O(n)

这当然不是一个非常优雅的解决方案,因为它几乎是greggo给出的正则表达式解决方案的黑客攻击。我认为,最糟糕的情况是len(s)^2并不是很糟糕,但绝对可能更好......

答案 2 :(得分:0)

这可以假设来自s的{​​{1}}中的元素由分隔符分隔,这里是一个空格:

让我们使用这个测试数据

L

首先,标记 s 并将其转换为集合:

s = "hello world foo foo"
L = set(["foo", "bar", "baz", "hello", "world"])

然后只需从tokenset = set(s.split()) 中减去L并检查结果是否为空:

tokenset