Làm thế nào để có được một chuỗi sau một chuỗi con cụ thể?


226

Làm thế nào tôi có thể có được một chuỗi sau một chuỗi con cụ thể?

Ví dụ, tôi muốn để có được những chuỗi sau "world"trongmy_string="hello python world , i'm a beginner "

Câu trả lời:


399

Cách dễ nhất có lẽ chỉ là phân chia từ mục tiêu của bạn

my_string="hello python world , i'm a beginner "
print my_string.split("world",1)[1] 

split sẽ lấy từ (hoặc ký tự) để phân tách và tùy ý giới hạn số lượng phân chia.

Trong ví dụ này phân chia trên "thế giới" và giới hạn nó chỉ một lần phân chia.


Nếu tôi cần tách một văn bản với từ 'thấp' và nó chứa từ thấp hơn trước nó, thì nó sẽ không hoạt động!
Leonardo Hermoso

1
bạn sẽ chia đôi đơn giảntarget.split('lower',1)[-1].split('low',1)[-1]
Joran Beasley

Sẽ thế nào nếu câu đó là "xin chào python Megaworld thế giới, tôi là người mới bắt đầu". Làm thế nào tôi có thể làm cho nó nhìn toàn bộ từ và không phải là một phần của từ khác như 'Megaworld'? Cảm ơn
pbou

1
sau đó chuỗi bạn tìm kiếm là "thế giới" ... hoặc sử dụng regex cho từ bị ràng buộc
Joran Beasley

6
my_string.partition("world")[-1](hoặc ...[2]) nhanh hơn.
Martijn Pieters

66
s1 = "hello python world , i'm a beginner "
s2 = "world"

print s1[s1.index(s2) + len(s2):]

Nếu bạn muốn để đối phó với các trường hợp s2không hiện diện trong s1, sau đó sử dụng s1.find(s2)như trái ngược với index. Nếu giá trị trả về của cuộc gọi đó là -1, thì s2không có trong s1.


bạn nhận được các id riêng biệt (cách nhau vài nghìn) ... tôi không chắc bạn không tạo các chuỗi con không cần thiết với điều này
Joran Beasley

@JoranBeasley, chúng tôi chỉ gọi index (), len () và lát. Không có lý do gì để index () và len () tạo ra các chuỗi con và nếu chúng làm (tôi thấy khó tin), đó chỉ là một chi tiết triển khai không cần thiết. Tương tự cho lát cắt - không có lý do gì để nó tạo ra các chuỗi con khác với lớp nền được trả về.
shx2

@ shx2print( s1[s1.index(s2) + len(s2):] is s1[s1.index(s2) + len(s2):])
Joran Beasley

@JoranBeasley bạn đang cố gắng thực hiện điểm nào với đoạn trích này? Đó là trên nhiều cuộc gọi đối tượng khác nhau được trả lại? bởi "các chuỗi con không cần thiết" Tôi có nghĩa là các chuỗi con khác với các chuỗi con được trả về, tức là các chuỗi con không cần thiết để tạo ra kết quả.
shx2

56

Tôi ngạc nhiên không ai nhắc đến partition.

def substring_after(s, delim):
    return s.partition(delim)[2]

IMHO, giải pháp này dễ đọc hơn @ arshajii. Ngoài ra, tôi nghĩ rằng @ arshajii là tốt nhất để trở thành người nhanh nhất - nó không tạo ra bất kỳ bản sao / chuỗi con không cần thiết nào.


2
Đây là một giải pháp tốt và xử lý trường hợp chuỗi con không phải là một phần của chuỗi cơ sở độc đáo.
mattmc3

bạn nhận được các id riêng biệt (cách nhau vài nghìn) ... tôi không chắc bạn không tạo các chuỗi con không cần thiết với điều này (và tôi quá lười để cấu hình đúng cách)
Joran Beasley

1
@JoranBeasley, rõ ràng tạo ra các trạm biến áp không cần thiết. Tôi nghĩ bạn đọc sai câu trả lời của tôi.
shx2

(tôi cũng nghĩ vậy về arashi ...)
Joran Beasley

3
Hơn nữa, điều này là nhanh hơn str.split(..., 1).
Martijn Pieters

20

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ế .

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 gốc, thì hãy kiểm tra xem giá trị thứ hai được trả về str.partition()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 là 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 trường hợp tốt nhất, nhanh hơnstr.partition() khoảng 15% so với str.split():

                                missing        first         lower         upper          last
      str.partition(...)[2]:  [3.745 usec]  [0.434 usec]  [1.533 usec]  <3.543 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.817 usec>  <0.518 usec>  <1.632 usec>  [3.191 usec]  <4.173 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 (kịch bản 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 [...]<...>đánh dấ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 thử nghiệm trên Python 3.7.4 trên Macbook Pro model 15 "với Intel Core i7 2.9 GHz và ram 16 GB.

Kịch bản 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, sẽ 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ả công bằng nhất cho các sự kiện hệ điều hành 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"<{row[c][1:-1]}>"
    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="  ")

câu trả lời chính xác! đặc biệt bởi vì bạn cung cấp lý do thực sự điều này tốt hơn: P
Joran Beasley

18

Nếu bạn muốn làm điều này bằng regex, bạn có thể chỉ cần sử dụng một nhóm không bắt giữ , để có được từ "thế giới" và sau đó lấy mọi thứ sau đó, như vậy

(?:world).*

Chuỗi ví dụ được thử nghiệm ở đây


28
Một số người khi gặp vấn đề nghĩ rằng "Tôi biết, Ill sử dụng một biểu thức thông thường." ... bây giờ bạn có 2 vấn đề ...
Joran Beasley

2
haha, lỗi của tôi, tôi nghĩ rằng đây là thẻ regex nên tôi đã cố gắng đưa ra câu trả lời regex. Ồ tốt, giờ nó đã ở đó.
Tadgh

1
tất cả đều tốt ... đó chắc chắn là một cách để lột da con mèo này ... quá mức cần thiết cho vấn đề này (imho)
Joran Beasley

Liên kết nhóm không bắt giữ không còn chỉ ra điều đúng.
Apterx

1
Dành cho những ai quan tâm. Đây là mã đầy đủresult = re.search(r"(?:world)(.*)", "hello python world , i'm a beginner ").group(1)
RaduS

5

Bạn có thể sử dụng gói này được gọi là "chuỗi con". Chỉ cần gõ "pip cài đặt chuỗi con". Bạn có thể nhận được chuỗi con bằng cách chỉ đề cập đến các ký tự / chỉ mục bắt đầu và kết thúc.

Ví dụ:

import substring

s = substring.substringByChar("abcdefghijklmnop", startChar="d", endChar="n")

print(s)

Đầu ra:

s = defghijklmn


3

Đó là một câu hỏi cũ nhưng tôi đã phải đối mặt với một kịch bản rất giống nhau, tôi cần phải phân tách một chuỗi bằng cách sử dụng từ "hạ thấp" vấn đề đối với tôi là tôi có cùng một chuỗi từ bên dưới và thấp hơn.

Tôi đã giải quyết nó bằng mô-đun re theo cách này

import re

string = '...below...as higher prices mean lower demand to be expected. Generally, a high reading is seen as negative (or bearish), while a low reading is seen as positive (or bullish) for the Korean Won.'

sử dụng re.split với regex để ghép từ chính xác

stringafterword = re.split('\\blow\\b',string)[-1]
print(stringafterword)
' reading is seen as positive (or bullish) for the Korean Won.'

mã chung là:

re.split('\\bTHE_WORD_YOU_WANT\\b',string)[-1]

Hy vọng điều này có thể giúp ai đó!


1
Có lẽ bạn cũng có thể sử dụng : string.partition(" low ")[2]? (Lưu ý các khoảng trắng ở hai bên củalow
Mtl Dev

1

Hãy thử phương pháp chung này:

import re
my_string="hello python world , i'm a beginner "
p = re.compile("world(.*)")
print (p.findall(my_string))

#[" , i'm a beginner "]

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.