我需要检查是否可以使用字符列表创建字符串并返回True或False。
我在list.count或collections.Counter中使用不同的解决方案。
我也在使用这个解决方案,我不需要阅读字符列表:
def check(message, characters):
try:
[list(characters).remove(m) for m in message]
return True
except:
return False
有最快的方法吗?对于一个非常非常大的角色列表。计数器和列表计数似乎较慢。不知道是否有快速的pythonic方法来做到这一点。
示例:
message = "hello"
characters = "hheellooasdadsfgfdgfdhgfdlkgkfd"
check(message, characters) # this should return True or False
# characters can be a veeeeery long string
重复事项,例如字符=" hheloo"不适用于message ="你好"
答案 0 :(得分:7)
您可以使用collections.Counter()
。只需构建两个计数器并使用subtract()
方法检查是否存在任何负数:
>>> c1 = Counter(characters)
>>> c2 = Counter(message)
>>> c1.subtract(c2)
>>> all(v >= 0 for v in c1.values())
False
这应该在线性时间内起作用。
答案 1 :(得分:1)
这在线性时间内是不可行的,因为两个字符串的长度很重要,并且需要为每个字符迭代它们。在没有检查其实际实现的情况下,我认为remove()
是对数的。
def check(msg, chars):
c = list(chars) # Creates a copy
try:
for m in msg:
c.remove(m)
except ValueError:
return False
return True
if __name__ == '__main__':
print(check('hello', 'ehlo'))
print(check('hello', 'ehlol'))
print(check('hello', 'ehloijin2oinscubnosinal'))
答案 2 :(得分:1)
与eugene的解决方案和jbndlr的解决方案相比,这是另一种解决方案。
def test1(input_word, alphabet):
alp_set = set(list(alphabet))
in_set = set(list(input_word))
return in_set.issubset(alp_set)
def test2(input_word, alphabet):
c1 = collections.Counter(alphabet)
c2 = collections.Counter(input_word)
c1.subtract(c2)
return all(v >= 0 for v in c1.values())
def check(msg, chars):
c = list(chars) # Creates a copy
try:
for m in msg:
c.remove(m)
except ValueError:
return False
return True
input_word = "hello"
alphabet = "hheellooasdadsfgfdgfdhgfdlkgkfd"
start_time = time.time()
for i in range(10000):
test1(input_word,alphabet)
print("--- %s seconds ---" % (time.time() - start_time))
start_time = time.time()
for i in range(10000):
test2(input_word,alphabet)
print("--- %s seconds ---" % (time.time() - start_time))
start_time = time.time()
for i in range(10000):
check(input_word,alphabet)
print("--- %s seconds ---" % (time.time() - start_time))
>> --- 0.03100299835205078 seconds ---
>> --- 0.24402451515197754 seconds ---
>> --- 0.022002220153808594 seconds ---
⇒jbndlr的解决方案是最快的 - 对于这个测试用例。
另一个测试用例:
input_word = "hellohellohellohellohellohellohellohellohellohellohellohellohello"
alphabet =
“hheellooasdadsfgfdgfdhgfdlkgkfdhheellooasdadsfgfdgfdhgfdlkgkfdhheellooasdadsfgfdgfdhgfdlkgkfdhheellooasdadsfgfdgfdhgfdlkgkfdhheellooasdadsfgfdgfdhgfdlkgkfdhheellooasdadsfgfdgfdhgfdlkgkfdhheellooasdadsfgfdgfdhgfdlkgkfdhheellooasdadsfgfdgfdhgfdlkgkfdhheellooasdadsfgfdgfdhgfdlkgkfdhheellooasdadsfgfdgfdhgfdlkgkfdhheellooasdadsfgfdgfdhgfdlkgkfdhheellooasdadsfgfdgfdhgfdlkgkfdhheellooasdadsfgfdgfdhgfdlkgkfdhheellooasdadsfgfdgfdhgfdlkgkfdhheellooasdadsfgfdgfdhgfdlkgkfdhheellooasdadsfgfdgfdhgfdlkgkfdhheellooasdadsfgfdgfdhgfdlkgkfdhheellooasdadsfgfdgfdhgfdlkgkfd”
>> --- 0.21964788436889648 seconds ---
>> --- 0.518169641494751 seconds ---
>> --- 1.3148927688598633 seconds ---
⇒test1是最快的
答案 3 :(得分:1)
有一种更快的方法可以做到这一点,显然是由于创建all()生成器(Why is Python's 'all' function so slow?)的成本,或许for循环更快,扩展@eugene y的回答:
from collections import Counter
import time
message = "hello"
characters = "hheeooasdadsfgfdgfdhgfdlkgkfd"
def check1(message,characters):
c1 = Counter(characters)
c2 = Counter(message)
c1.subtract(c2)
return all(v > -1 for v in c1.values())
def check2(message,characters):
c1 = Counter(characters)
c2 = Counter(message)
c1.subtract(c2)
for v in c1.values():
if v < 0:
return False
return True
st = time.time()
for i in range(350000):
check1(message,characters)
end = time.time()
print ("all(): "+str(end-st))
st = time.time()
for i in range(350000):
check2(message,characters)
end = time.time()
print ("for loop: "+str(end-st))
结果:
all(): 5.201688051223755
for loop: 4.864434719085693