web-dev-qa-db-fra.com

Obtenir une chaîne après une sous-chaîne spécifique

comment puis-je obtenir une chaîne après une sous-chaîne spécifique.

Par exemple, je veux obtenir la chaîne après "world" dans my_string="hello python world , i'm a beginner "

170
havox

Le moyen le plus simple est probablement de diviser votre cible Word

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

split prend le mot (ou le caractère) sur lequel diviser et éventuellement une limite au nombre de divisions.

Dans cet exemple, divisez le mot "monde" et limitez-le à un seul fractionnement.

313
Joran Beasley
s1 = "hello python world , i'm a beginner "
s2 = "world"

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

Si vous voulez traiter le cas où s2 est not présent dans s1, utilisez s1.find(s2) par opposition à index. Si la valeur de retour de cet appel est -1, alors s2 n'est pas dans s1.

55
arshajii

Je suis surpris que personne n'ait mentionné partition.

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

IMHO, cette solution est plus lisible que celle de @ arshajii. À part cela, je pense que @ arshajii est le meilleur pour être le plus rapide - il ne crée pas de copies/sous-chaînes inutiles.

42
shx2

Si vous voulez faire cela en utilisant regex, vous pouvez simplement utiliser un groupe qui ne capture pas , pour obtenir le mot "monde" puis tout récupérer après, comme ça

(?:world).*

La chaîne d'exemple est testée ici

17
Tadgh

Vous pouvez utiliser ce paquetage appelé "sous-chaîne". Il suffit de taper "pip install substring". Vous pouvez obtenir la sous-chaîne en mentionnant simplement les caractères/index de début et de fin.

Par exemple:

import substring

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

print(s)

Sortie:

s = defghijklmn

3
Sriram Veturi

C'est une vieille question, mais je suis confronté au même scénario. Je dois diviser une chaîne en utilisant comme démiliter le mot "low". Le problème pour moi, c'est que j'ai dans la même chaîne le mot en dessous et inférieur.

Je l'ai résolu en utilisant le module re de cette façon

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

utilisez re.split avec regex pour faire correspondre le mot exact

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

le code générique est:

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

J'espère que cela peut aider quelqu'un!

3
Leonardo Hermoso

Vous voulez utiliser str.partition() :

>>> my_string.partition("world")[2]
" , i'm a beginner "

parce que cette option est plus rapide que les alternatives .

Notez que cela produit une chaîne vide si le délimiteur est manquant:

>>> my_string.partition("Monty")[2]  # delimiter missing
''

Si vous voulez avoir la chaîne d'origine, testez si la seconde valeur renvoyée par str.partition() est non vide:

prefix, success, result = my_string.partition(delimiter)
if not success: result = prefix

Vous pouvez aussi utiliser str.split() avec une limite de 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 "

Cependant, cette option est plus lente . Dans le meilleur des cas, str.partition() est facilement environ 15% plus rapide par rapport à 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%

Cela montre les temps par exécution avec les entrées ici, le délimiteur est soit manquant (pire des cas), soit placé en premier (meilleur des cas), ou dans la moitié inférieure, la moitié supérieure ou la dernière position. Le temps le plus rapide est marqué avec [...] et <...> marque le pire.

Le tableau ci-dessus est produit par un essai chronométrique complet pour les trois options, produit ci-dessous. J'ai effectué les tests sur Python 3.7.4 sur un Macbook Pro 15 ", modèle 2017, avec Intel Core i7 à 2,9 GHz et 16 Go de RAM.

Ce script génère des phrases aléatoires avec et sans le délimiteur sélectionné de manière aléatoire et, s'il est présent, à différentes positions de la phrase générée, exécute les tests dans un ordre aléatoire avec répétitions (en produisant les résultats les plus justes pour les événements de système d'exploitation aléatoires se déroulant au cours des tests), puis imprime un tableau des résultats:

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="  ")
3
Martijn Pieters