是否有一种优雅的方式(最好是pythonic)来检查String s 是否是set L 子集元素的串联? L 的元素可能会在 s 中出现多次。
例如:
L = set(["a", "ab", "c", "e"])
然后“abac”是 L
子集元素的有效串联“aaaaaaa”也是有效的连接。
但“ad”不是因为“d”不在L中。
答案 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