[英]Fastest way to check if a string can be created with a list of characters in python
I need to check if a string can be created with a list of characters and return True or False. 我需要检查是否可以使用字符列表创建字符串并返回True或False。
I am using different solutions with list.count or collections.Counter. 我正在使用list.count或collections.Counter的不同解决方案。
I am also using this solution which I dont need to read through the list of characters: 我也在使用这个解决方案,我不需要通读字符列表:
def check(message, characters):
try:
[list(characters).remove(m) for m in message]
return True
except:
return False
Is there a fastest way? 有最快的方式吗? for a very very very big list of characters.
对于一个非常非常大的角色列表。 Counter and list count seems slower.
计数器和列表计数似乎较慢。 Dont know if there is a fast pythonic way to do this.
不知道是否有快速的pythonic方式来做到这一点。
Example: 例:
message = "hello"
characters = "hheellooasdadsfgfdgfdhgfdlkgkfd"
check(message, characters) # this should return True or False
# characters can be a veeeeery long string
Duplicates matter so for example characters = "hheloo" would not work for message = "hello" 重复事项 ,例如characters =“hheloo”不适用于message =“hello”
You could use collections.Counter()
. 您可以使用
collections.Counter()
。 Just build two counters and use the subtract()
method to check if there're any negative counts: 只需构建两个计数器并使用
subtract()
方法检查是否有任何负数:
>>> c1 = Counter(characters)
>>> c2 = Counter(message)
>>> c1.subtract(c2)
>>> all(v >= 0 for v in c1.values())
False
This should work in linear time. 这应该在线性时间内起作用。
This is not feasible in linear time, as the length of both strings matter and they need to be iterated for each character. 这在线性时间内是不可行的,因为两个字符串的长度都很重要,并且需要为每个字符迭代它们。 Without having checked its actual implementation, I assume
remove()
is logarithmic. 在没有检查其实际实现的情况下,我假设
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'))
Here is another solution compared to eugene's solution and jbndlr's solution. 与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's solution is the fastest - for this test case. ⇒jbndlr的解决方案是最快的 - 对于这个测试用例。
Another testcase: 另一个测试用例:
input_word = "hellohellohellohellohellohellohellohellohellohellohellohellohello"
alphabet =
"" “”
>> --- 0.21964788436889648 seconds ---
>> --- 0.518169641494751 seconds ---
>> --- 1.3148927688598633 seconds ---
⇒ test1 is fastest ⇒test1是最快的
There is maybe a faster way of doing this, apparently due to the cost of creating the all() generator ( Why is Python's 'all' function so slow? ) perhaps a for loop is faster, Expanding on @eugene y's answer: 有一种更快的方法可以做到这一点,显然是由于创建all()生成器的成本( 为什么Python的'all'函数如此慢? )也许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))
results: 结果:
all(): 5.201688051223755
for loop: 4.864434719085693
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.