Bạn muốn sử dụng str.partition[]
:
>>> my_string.partition["world"][2]
" , i'm a beginner "
Bởi vì tùy chọn này nhanh hơn các lựa chọn thay thế.faster than the alternatives.
Lưu ý rằng điều này tạo ra một chuỗi trống nếu thiếu dấu phân cách:
>>> my_string.partition["Monty"][2] # delimiter missing
''
Nếu bạn muốn có chuỗi ban đầu, thì hãy kiểm tra xem giá trị thứ hai được trả về từ str.partition[]
là không trống:
prefix, success, result = my_string.partition[delimiter]
if not success: result = prefix
Bạn cũng có thể sử dụng str.split[]
với giới hạn 1:
>>> my_string.split["world", 1][-1]
" , i'm a beginner "
>>> my_string.split["Monty", 1][-1] # delimiter missing
"hello python world , i'm a beginner "
Tuy nhiên, tùy chọn này chậm hơn. Đối với một trường hợp tốt nhất, str.partition[]
dễ dàng nhanh hơn khoảng 15% so với str.split[]
:slower. For a best-case scenario, str.partition[]
is easily about 15% faster compared to str.split[]
:
missing first lower upper last
str.partition[...][2]: [3.745 usec] [0.434 usec] [1.533 usec] [4.075 usec]
str.partition[...] and test: 3.793 usec 0.445 usec 1.597 usec 3.208 usec 4.170 usec
str.split[..., 1][-1]: [3.191 usec]
% best vs worst: 1.9% 16.2% 6.1% 9.9% 2.3%
Điều này cho thấy thời gian trên mỗi lần thực hiện với các đầu vào ở đây, dấu phân cách bị thiếu [trường hợp xấu nhất], được đặt đầu tiên [kịch bản trường hợp tốt nhất] hoặc ở nửa dưới, nửa trên hoặc vị trí cuối cùng. Thời gian nhanh nhất được đánh dấu bằng
>>> my_string.partition["Monty"][2] # delimiter missing
''
1 và >>> my_string.partition["Monty"][2] # delimiter missing
''
2 đánh dấu điều tồi tệ nhất.Bảng trên được sản xuất bởi một thử nghiệm thời gian toàn diện cho cả ba tùy chọn, được sản xuất dưới đây. Tôi đã chạy các bài kiểm tra trên Python 3.7.4 trên Model 15 "MacBook Pro 2017 với RAM Intel I7 và 16 GB 2,9 GHz.
Tập lệnh này tạo ra các câu ngẫu nhiên có và không có dấu phân cách được chọn ngẫu nhiên và nếu có, tại các vị trí khác nhau trong câu được tạo, chạy các thử nghiệm theo thứ tự ngẫu nhiên với các lần lặp lại [tạo ra kết quả hợp lý nhất cho các sự kiện HĐH ngẫu nhiên diễn ra trong quá trình thử nghiệm], và sau đó in một bảng kết quả:
import random
from itertools import product
from operator import itemgetter
from pathlib import Path
from timeit import Timer
setup = "from __main__ import sentence as s, delimiter as d"
tests = {
"str.partition[...][2]": "r = s.partition[d][2]",
"str.partition[...] and test": [
"prefix, success, result = s.partition[d]\n"
"if not success: result = prefix"
],
"str.split[..., 1][-1]": "r = s.split[d, 1][-1]",
}
placement = "missing first lower upper last".split[]
delimiter_count = 3
wordfile = Path["/usr/dict/words"] # Linux
if not wordfile.exists[]:
# macos
wordfile = Path["/usr/share/dict/words"]
words = [w.strip[] for w in wordfile.open[]]
def gen_sentence[delimiter, where="missing", l=1000]:
"""Generate a random sentence of length l
The delimiter is incorporated according to the value of where:
"missing": no delimiter
"first": delimiter is the first word
"lower": delimiter is present in the first half
"upper": delimiter is present in the second half
"last": delimiter is the last word
"""
possible = [w for w in words if delimiter not in w]
sentence = random.choices[possible, k=l]
half = l // 2
if where == "first":
# best case, at the start
sentence[0] = delimiter
elif where == "lower":
# lower half
sentence[random.randrange[1, half]] = delimiter
elif where == "upper":
sentence[random.randrange[half, l]] = delimiter
elif where == "last":
sentence[-1] = delimiter
# else: worst case, no delimiter
return " ".join[sentence]
delimiters = random.choices[words, k=delimiter_count]
timings = {}
sentences = [
# where, delimiter, sentence
[w, d, gen_sentence[d, w]] for d, w in product[delimiters, placement]
]
test_mix = [
# label, test, where, delimiter sentence
[*t, *s] for t, s in product[tests.items[], sentences]
]
random.shuffle[test_mix]
for i, [label, test, where, delimiter, sentence] in enumerate[test_mix, 1]:
print[f"\rRunning timed tests, {i:2d}/{len[test_mix]}", end=""]
t = Timer[test, setup]
number, _ = t.autorange[]
results = t.repeat[5, number]
# best time for this specific random sentence and placement
timings.setdefault[
label, {}
].setdefault[
where, []
].append[min[dt / number for dt in results]]
print[]
scales = [[1.0, 'sec'], [0.001, 'msec'], [1e-06, 'usec'], [1e-09, 'nsec']]
width = max[map[len, timings]]
rows = []
bestrow = dict.fromkeys[placement, [float["inf"], None]]
worstrow = dict.fromkeys[placement, [float["-inf"], None]]
for row, label in enumerate[tests]:
columns = []
worst = float["-inf"]
for p in placement:
timing = min[timings[label][p]]
if timing < bestrow[p][0]:
bestrow[p] = [timing, row]
if timing > worstrow[p][0]:
worstrow[p] = [timing, row]
worst = max[timing, worst]
columns.append[timing]
scale, unit = next[[s, u] for s, u in scales if worst >= s]
rows.append[
[f"{label:>{width}}:", *[f" {c / scale:.3f} {unit} " for c in columns]]
]
colwidth = max[len[c] for r in rows for c in r[1:]]
print[' ' * [width + 1], *[p.center[colwidth] for p in placement], sep=" "]
for r, row in enumerate[rows]:
for c, p in enumerate[placement, 1]:
if bestrow[p][1] == r:
row[c] = f"[{row[c][1:-1]}]"
elif worstrow[p][1] == r:
row[c] = f""
print[*row, sep=" "]
percentages = []
for p in placement:
best, worst = bestrow[p][0], worstrow[p][0]
ratio = [[worst - best] / worst]
percentages.append[f"{ratio:{colwidth - 1}.1%} "]
print["% best vs worst:".rjust[width + 1], *percentages, sep=" "]