Як би я отримав усе перед a: у рядку Python


106

Я шукаю спосіб отримати всі літери в рядку перед a: але я не знаю, з чого почати. Я б використав регулярний вираз? Якщо так, то як?

string = "Username: How are you today?"

Хтось може показати мені приклад того, що я міг зробити?

Відповіді:


177

Просто використовуйте splitфункцію. Він повертає список, тому ви можете зберегти перший елемент:

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

12
Або обмежте розкол, або в даному випадку - використовуйтеs1.partition(':')[0]
Джон Клементс

Дякую, це було дуже корисно та інформативно. Плюс це велика допомога дякую!
0Cool

2
Не використовуйте split, оскільки він обробляє все ':' і створює повний масив, що не підходить для довших рядків. Див. Підхід @ Hackaholic до використання індексу. Тільки це також рекомендує регулярний вираз, який явно не такий ефективний. Також повинен бути параметр python для виконання стандартної операції .substringBefore (), яка базується на індексі. А також такі варіації, як .substringBeforeLast () тощо, повинні бути там для зручності (код не повинен повторюватися). Помітив пункт про розділ - так, менше обробки після ':', але все одно повертає <клас 'кортеж'>: ('1', ':', '2: 3'), а не '1'.
arntg

46

Використання index:

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

Індекс покаже вам позицію :в рядку, тоді ви можете нарізати його.

Якщо ви хочете використовувати регулярний вираз:

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

match збіги з початку рядка.

Ви також можете використовувати itertools.takewhile

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

3
Цей метод (рядок [: string.index (":")]), ймовірно, чистіший за розкол
Деймієн,

Для швидкості не використовуйте регулярний вираз - використовуйте перший параметр індексу, згаданий тут. Regex явно не такий ефективний. Також повинен бути параметр python для виконання стандартної операції .substringBefore (), яка базується на індексі. А також такі варіації, як .substringBeforeLast () тощо, повинні бути там для зручності (код не повинен повторюватися). Запропонуйте оновити цю відповідь, щоб пояснити, чому індекс працює краще, а потім чому його слід застосовувати в порівнянні з іншими підходами, включаючи той, що проголосував вище у відповіді Фредтантіні.
arntg

Якщо його немає, індекс не вдасться.
Марк

19

Вам не потрібно regexдля цього

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

За допомогою splitметоду можна розділити рядок на ':'символ

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

І виріжте елемент, [0]щоб отримати першу частину рядка

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

8

Я порівняв ці різні техніки під Python 3.7.0 (IPython).

TLDR

  • найшвидший (коли cвідомий символ розділення ): попередньо скомпільований регулярний вираз.
  • Самий швидкий ( в іншому випадку) s.partition(c)[0].
  • безпечно (тобто, коли cможе не знаходитись s): розділ, розділення.
  • небезпечно: індекс, регулярний вираз.

Код

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]

Результати

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)

1
чому ви вважаєте індекс небезпечним?
Джеймс

3
s.index(c)викликає ValueError, коли cйого немає s. Отже, я вважаю безпечним, коли впевнений, що рядок, який потрібно розділити, містить роздільник, інакше небезпечно.
Арістід,

1
Для індексу c дорівнює s, тому він не є небезпечним і все ще найшвидшим.
arntg

2

розділ () може бути краще, ніж split () для цієї мети, оскільки він має кращі передбачувані результати для ситуацій, у яких у вас немає роздільника або більше роздільників.


1
І те, partitionі інше splitбуде працювати прозоро з порожнім рядком або без роздільників. Варто зазначити, що це word[:word.index(':')]з’явиться в обох випадках.
Роб Холл,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.