Làm cách nào để tôi có được mọi thứ trước a: trong một chuỗi Python


102

Tôi đang tìm cách lấy tất cả các ký tự trong một chuỗi trước a: nhưng tôi không biết bắt đầu từ đâu. Tôi có sử dụng regex không? Nếu vậy thì làm thế nào?

string = "Username: How are you today?"

Ai đó có thể chỉ cho tôi một ví dụ về những gì tôi có thể làm được không?

Câu trả lời:


169

Chỉ cần sử dụng splitchức năng. Nó trả về một danh sách, vì vậy bạn có thể giữ phần tử đầu tiên:

>>> s1.split(':')
['Username', ' How are you today?']
>>> s1.split(':')[0]
'Username'

12
Hoặc giới hạn sự phân tách hoặc trong trường hợp này - sử dụngs1.partition(':')[0]
Jon Clements

Cảm ơn bạn, điều này rất hữu ích và nhiều thông tin. Plus nó wa sa giúp đỡ lớn cảm ơn!
0Cool

1
Không sử dụng phân tách, vì nó đang xử lý tất cả ':' và tạo ra một mảng đầy đủ, không tốt cho các chuỗi dài hơn. Xem cách tiếp cận của @ Hackaholic để sử dụng chỉ mục. Chỉ là một người cũng đang đề xuất một regex mà rõ ràng là không hiệu quả. Ngoài ra, phải có một tùy chọn python để thực hiện hoạt động tiêu chuẩn của .substringBefore () dựa trên chỉ mục. Và các biến thể như .substringBeforeLast (), v.v. cũng nên ở đó để thuận tiện (không nên lặp lại mã). Lưu ý điểm về phân vùng - có, ít xử lý hơn sau ':', nhưng vẫn trả về <class 'tuple'>: ('1', ':', '2: 3') thay vì '1'.
arntg

43

Sử dụng index:

>>> string = "Username: How are you today?"
>>> string[:string.index(":")]
'Username'

Chỉ mục sẽ cung cấp cho bạn vị trí của :chuỗi, sau đó bạn có thể cắt nó.

Nếu bạn muốn sử dụng regex:

>>> import re
>>> re.match("(.*?):",string).group()
'Username'                       

match khớp từ đầu chuỗi.

bạn cũng có thể dùng itertools.takewhile

>>> import itertools
>>> "".join(itertools.takewhile(lambda x: x!=":", string))
'Username'

3
Phương thức này (string [: string.index (":")]) có lẽ rõ ràng hơn so với phương thức phân tách
Damien

Đối với tốc độ, không sử dụng regex - sử dụng tùy chọn chỉ mục đầu tiên được đề cập ở đây. Regex rõ ràng là không hiệu quả. Ngoài ra, phải có một tùy chọn python để thực hiện hoạt động tiêu chuẩn của .substringBefore () dựa trên chỉ mục. Và các biến thể như .substringBeforeLast (), v.v. cũng nên ở đó để thuận tiện (không nên lặp lại mã). Đề nghị cập nhật câu trả lời này để giải thích lý do tại sao chỉ mục hoạt động tốt hơn và sau đó tại sao điều này nên được sử dụng trên các phương pháp tiếp cận khác, bao gồm cả phương pháp được bình chọn cao hơn hiện nay trong phản hồi của fredtantini.
arntg

Nếu nó không xuất hiện, chỉ mục sẽ không thành công.
Marc

18

Bạn không cần regexđiều này

>>> s = "Username: How are you today?"

Bạn có thể sử dụng splitphương pháp để tách chuỗi trên ':'ký tự

>>> s.split(':')
['Username', ' How are you today?']

Và cắt phần tử [0]để lấy phần đầu tiên của chuỗi

>>> s.split(':')[0]
'Username'

7

Tôi đã đánh giá các kỹ thuật khác nhau này trong Python 3.7.0 (IPython).

TLDR

  • nhanh nhất (khi biết ký hiệu tách c): regex được biên dịch trước.
  • nhanh nhất (nếu không): s.partition(c)[0].
  • safe (tức là, khi ccó thể không ở trong s): phân vùng, phân chia.
  • không an toàn: chỉ mục, regex.

import string, random, re

SYMBOLS = string.ascii_uppercase + string.digits
SIZE = 100

def create_test_set(string_length):
    for _ in range(SIZE):
        random_string = ''.join(random.choices(SYMBOLS, k=string_length))
        yield (random.choice(random_string), random_string)

for string_length in (2**4, 2**8, 2**16, 2**32):
    print("\nString length:", string_length)
    print("  regex (compiled):", end=" ")
    test_set_for_regex = ((re.compile("(.*?)" + c).match, s) for (c, s) in test_set)
    %timeit [re_match(s).group() for (re_match, s) in test_set_for_regex]
    test_set = list(create_test_set(16))
    print("  partition:       ", end=" ")
    %timeit [s.partition(c)[0] for (c, s) in test_set]
    print("  index:           ", end=" ")
    %timeit [s[:s.index(c)] for (c, s) in test_set]
    print("  split (limited): ", end=" ")
    %timeit [s.split(c, 1)[0] for (c, s) in test_set]
    print("  split:           ", end=" ")
    %timeit [s.split(c)[0] for (c, s) in test_set]
    print("  regex:           ", end=" ")
    %timeit [re.match("(.*?)" + c, s).group() for (c, s) in test_set]

Các kết quả

String length: 16
  regex (compiled): 156 ns ± 4.41 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
  partition:        19.3 µs ± 430 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
  index:            26.1 µs ± 341 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  split (limited):  26.8 µs ± 1.26 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  split:            26.3 µs ± 835 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  regex:            128 µs ± 4.02 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

String length: 256
  regex (compiled): 167 ns ± 2.7 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
  partition:        20.9 µs ± 694 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  index:            28.6 µs ± 2.73 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  split (limited):  27.4 µs ± 979 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  split:            31.5 µs ± 4.86 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  regex:            148 µs ± 7.05 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

String length: 65536
  regex (compiled): 173 ns ± 3.95 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
  partition:        20.9 µs ± 613 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
  index:            27.7 µs ± 515 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  split (limited):  27.2 µs ± 796 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  split:            26.5 µs ± 377 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  regex:            128 µs ± 1.5 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

String length: 4294967296
  regex (compiled): 165 ns ± 1.2 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
  partition:        19.9 µs ± 144 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
  index:            27.7 µs ± 571 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  split (limited):  26.1 µs ± 472 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  split:            28.1 µs ± 1.69 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  regex:            137 µs ± 6.53 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

tại sao bạn coi chỉ mục không an toàn?
James

2
s.index(c)tăng lỗi ValueError khi ckhông ở trong s. Vì vậy, tôi coi nó là an toàn khi tôi chắc chắn rằng chuỗi được phân vùng có chứa dấu phân tách, không an toàn nếu không.
Aristide

Đối với chỉ số, c là s nên không an toàn và vẫn nhanh nhất.
arntg

2

partition () có thể tốt hơn nên split () cho mục đích này vì nó có kết quả dự đoán tốt hơn cho các trường hợp bạn không có dấu phân tách hoặc nhiều dấu phân cách hơn.


1
Cả hai partitionsplitsẽ hoạt động minh bạch với một chuỗi rỗng hoặc không có dấu phân cách. Điều đáng chú ý là word[:word.index(':')]sẽ bật ra trong cả hai trường hợp này.
Rob Hall
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.