Một giải pháp mà không sử dụng bất kỳ hàng nhập khẩu sẽ được chuyển đổi chuỗi đến một iterator và trong thời gian lặp lấy ký tự tiếp theo bằng cách gọi tiếp theo trên iterator:
>>> s = "abcdefghijklmnopqrstuvwxyz"
>>> it = iter(s)
>>> ''.join(next(it, '') + c for c in it)
'badcfehgjilknmporqtsvuxwzy'
Thời gian:
>>> s = "abcdefghijklmnopqrstuvwxyz" * 10**5
>>> def func_next_no_cache(s):
it = iter(s)
return ''.join([next(it, '') + c for c in it])
...
>>> %timeit func_next_no_cache(s)
1 loops, best of 3: 291 ms per loop
Nhưng các cuộc gọi đến next
đang thực sự làm chậm xuống vì tìm kiếm next
Python có để đi đến builtins bắt đầu từ phạm vi địa phương, chúng ta hãy nhớ cache nó và thử lại:
>>> def func_next_cache(s, next=next):
it = iter(s)
return ''.join([next(it, '') + c for c in it])
...
>>> %timeit func_next_cache(s)
1 loops, best of 3: 241 ms per loop
Nhưng giải pháp nhanh nhất sẽ được sử dụng itertools.izip_longest
:
>>> from itertools import izip_longest
>>> def func_izip_l(s):
it = iter(s)
return "".join([b+a for a, b in izip_longest(it, it, fillvalue='')])
...
>>> %timeit func_izip_l(s)
1 loops, best of 3: 209 ms per loop
@ đang Joran cũng rất gần với trang này khi được sử dụng với một danh sách thay vì biểu hiện máy phát điện, nhưng nó tạo ra hai chuỗi bổ sung trong bộ nhớ:
>>> %timeit "".join([b+a for a, b in izip_longest(s[::2], s[1::2], fillvalue="")])
1 loops, best of 3: 212 ms per loop
Note rằng chúng ta nên luôn luôn ăn một list
-str.join
nếu tốc độ là một mối quan tâm: https://stackoverflow.com/a/9061024/846892
chiều dài Sẽ là thậm chí luôn? – thefourtheye
@thefourtheye Không **. Nhân tiện, cách tôi đăng vẫn hoạt động với một chuỗi có chiều dài không bằng nhau. – Jack
Bạn mong đợi kết quả như thế nào nếu bạn muốn nhận được 3 ký tự? – thefourtheye