Hoe verwijder ik een subtekenreeks aan het einde van een tekenreeks?

Ik heb de volgende code:

url = 'abcdc.com'
print(url.strip('.com'))

Ik verwachtte: abcdc

Ik heb: abcd

Nu doe ik

url.rsplit('.com', 1)

Is er een betere manier?


Antwoord 1, autoriteit 100%

stripbetekent niet “verwijder deze subtekenreeks”. x.strip(y)behandelt yals een set tekens en verwijdert alle tekens in die set van beide uiteinden van x.

Op Python 3.9 en nieuwerkun je de gebruiken removeprefixen removesuffixmethoden om een hele substring van beide kanten van de string te verwijderen:

url = 'abcdc.com'
url.removesuffix('.com')    # Returns 'abcdc'
url.removeprefix('abcdc.')  # Returns 'com'

Het relevante voorstel voor verbetering van Python is PEP-616.

Op Python 3.8 en ouderkun je endswithen snijden:

url = 'abcdc.com'
if url.endswith('.com'):
    url = url[:-4]

Of een gewone uitdrukking:

import re
url = 'abcdc.com'
url = re.sub('\.com$', '', url)

Antwoord 2, autoriteit 15%

Als je zeker weet dat de string alleen aan het einde verschijnt, dan is de eenvoudigste manier om ‘replace’ te gebruiken:

url = 'abcdc.com'
print(url.replace('.com',''))

Antwoord 3, autoriteit 8%

def strip_end(text, suffix):
    if suffix and text.endswith(suffix):
        return text[:-len(suffix)]
    return text

Antwoord 4, autoriteit 8%

Omdat het lijkt alsof niemand hier nog op heeft gewezen:

url = "www.example.com"
new_url = url[:url.rfind(".")]

Dit zou efficiënter moeten zijn dan de methoden die split()gebruiken, aangezien er geen nieuw lijstobject wordt gemaakt, en deze oplossing werkt voor strings met meerdere punten.


Antwoord 5, autoriteit 4%

Hangt af van wat je weet over je URL en wat je precies probeert te doen. Als je weet dat het altijd op ‘.com’ (of ‘.net’ of ‘.org’) eindigt, dan

url=url[:-4]

is de snelste oplossing. Als het meer algemene URL’s zijn, kun je waarschijnlijk beter in de urlparse-bibliotheek kijken die bij python wordt geleverd.

Als je daarentegen gewoon alles wilt verwijderen na de laatste ‘.’ in een string dan

url.rsplit('.',1)[0]

zal werken. Of als je gewoon alles wilt tot de eerste ‘.’ probeer dan

url.split('.',1)[0]

Antwoord 6, autoriteit 4%

Vanaf Python 3.9kunt u removesuffixin plaats daarvan:

'abcdc.com'.removesuffix('.com')
# 'abcdc'

Antwoord 7, autoriteit 2%

Als je weet dat het een extensie is, dan

url = 'abcdc.com'
...
url.rsplit('.', 1)[0]  # split at '.', starting from the right, maximum 1 split

Dit werkt even goed met abcdc.comof www.abcdc.comof abcdc.[anything]en is beter uitbreidbaar.


Antwoord 8, autoriteit 2%

Elke Python-versie:

def remove_suffix(text, suffix):
    return text[:-len(suffix)] if text.endswith(suffix) and len(suffix) != 0 else text

Python 3.9+

text.removesuffix(suffix)

Antwoord 9

Hoe zit het met url[:-4]?


Antwoord 10

Voor URL’s (aangezien het een onderdeel van het onderwerp lijkt te zijn door het gegeven voorbeeld), kan men zoiets als dit doen:

import os
url = 'http://www.stackoverflow.com'
name,ext = os.path.splitext(url)
print (name, ext)
#Or:
ext = '.'+url.split('.')[-1]
name = url[:-len(ext)]
print (name, ext)

Beide zullen het volgende uitvoeren:
('http://www.stackoverflow', '.com')

Dit kan ook worden gecombineerd met str.endswith(suffix)als u “.com” of iets specifieks wilt splitsen.


Antwoord 11

DSCLAIMERDeze methode heeft een kritieke fout doordat de partitie niet verankerd is aan het einde van de url en valse resultaten kan opleveren. Het resultaat voor de URL “www.comcast.net” is bijvoorbeeld “www” (onjuist) in plaats van de verwachte “www.comcast.net”. Deze oplossing is daarom slecht. Gebruik het niet tenzij u weet wat u doet!

url.rpartition('.com')[0]

Dit is vrij eenvoudig te typen en retourneert ook correct de originele tekenreeks (geen fout) wanneer het achtervoegsel ‘.com’ ontbreekt in url.


Antwoord 12

Als u alleen de extensie wilt verwijderen:

'.'.join('abcdc.com'.split('.')[:-1])
# 'abcdc'

Het werkt met elke extensie, met mogelijke andere punten die ook in de bestandsnaam voorkomen. Het splitst de string eenvoudig als een lijst op punten en voegt het samen zonder het laatste element.


Antwoord 13

Ervan uitgaande dat u het domein wilt verwijderen, ongeacht wat het is (.com, .net, enz.). Ik raad aan om de .te zoeken en vanaf dat moment alles te verwijderen.

url = 'abcdc.com'
dot_index = url.rfind('.')
url = url[:dot_index]

Hier gebruik ik rfindom het probleem van urls zoals abcdc.com.netop te lossen, die teruggebracht moeten worden tot de naam abcdc.com.

Als je je ook zorgen maakt over www.s, moet je hier expliciet naar kijken:

if url.startswith("www."):
   url = url.replace("www.","", 1)

De 1 in Replace is voor vreemde edgecases zoals www.net.www.com

Als je url nog wilder wordt, kijk dan naar de reguliere antwoorden waarmee mensen hebben gereageerd.


Antwoord 14

Als je een uiteinde van een string moet strippen als deze bestaat, doe dan niets. Mijn beste oplossingen. Je zult waarschijnlijk een van de eerste 2 implementaties willen gebruiken, maar ik heb de 3e toegevoegd voor de volledigheid.

Voor een constant achtervoegsel:

def remove_suffix(v, s):
    return v[:-len(s)] if v.endswith(s) else v
remove_suffix("abc.com", ".com") == 'abc'
remove_suffix("abc", ".com") == 'abc'

Voor een regex:

def remove_suffix_compile(suffix_pattern):
    r = re.compile(f"(.*?)({suffix_pattern})?$")
    return lambda v: r.match(v)[1]
remove_domain = remove_suffix_compile(r"\.[a-zA-Z0-9]{3,}")
remove_domain("abc.com") == "abc"
remove_domain("sub.abc.net") == "sub.abc"
remove_domain("abc.") == "abc."
remove_domain("abc") == "abc"

Voor een verzameling constante achtervoegsels de asymptotisch snelste manier voor een groot aantal oproepen:

def remove_suffix_preprocess(*suffixes):
    suffixes = set(suffixes)
    try:
        suffixes.remove('')
    except KeyError:
        pass
    def helper(suffixes, pos):
        if len(suffixes) == 1:
            suf = suffixes[0]
            l = -len(suf)
            ls = slice(0, l)
            return lambda v: v[ls] if v.endswith(suf) else v
        si = iter(suffixes)
        ml = len(next(si))
        exact = False
        for suf in si:
            l = len(suf)
            if -l == pos:
                exact = True
            else:
                ml = min(len(suf), ml)
        ml = -ml
        suffix_dict = {}
        for suf in suffixes:
            sub = suf[ml:pos]
            if sub in suffix_dict:
                suffix_dict[sub].append(suf)
            else:
                suffix_dict[sub] = [suf]
        if exact:
            del suffix_dict['']
            for key in suffix_dict:
                suffix_dict[key] = helper([s[:pos] for s in suffix_dict[key]], None)
            return lambda v: suffix_dict.get(v[ml:pos], lambda v: v)(v[:pos])
        else:
            for key in suffix_dict:
                suffix_dict[key] = helper(suffix_dict[key], ml)
            return lambda v: suffix_dict.get(v[ml:pos], lambda v: v)(v)
    return helper(tuple(suffixes), None)
domain_remove = remove_suffix_preprocess(".com", ".net", ".edu", ".uk", '.tv', '.co.uk', '.org.uk')

de laatste is waarschijnlijk aanzienlijk sneller in pypy dan in cpython. De regex-variant is waarschijnlijk sneller dan dit voor vrijwel alle gevallen waarin geen enorme woordenboeken met mogelijke achtervoegsels nodig zijn die niet gemakkelijk kunnen worden weergegeven als een regex, althans in cPython.

In PyPy is de regex-variant vrijwel zeker langzamer voor een groot aantal aanroepen of lange reeksen, zelfs als de re-module een DFA-compilerende regex-engine gebruikt, aangezien het overgrote deel van de overhead van de lambda’s door de JIT zal worden geoptimaliseerd.

In cPython weegt het feit dat uw draaiende c-code voor de regex-vergelijking echter vrijwel zeker op tegen de algoritmische voordelen van de achtervoegselverzamelingsversie in bijna alle gevallen.

Bewerken: https://m.xkcd.com/859/


Antwoord 15

Omdat dit een zeer populaire vraag is, voeg ik een andere, nu beschikbare, oplossing toe. Met python 3.9 (https://docs.python.org/3.9/whatsnew/3.9. html) de functie removesuffix()zal worden toegevoegd (en removeprefix()) en deze functie is precies wat hier werd gevraagd.

url = 'abcdc.com'
print(url.removesuffix('.com'))

uitvoer:

'abcdc'

PEP 616 (https://www.python.org/dev/peps /pep-0616/) laat zien hoe het zich gedraagt(het is niet de echte implementatie):

def removeprefix(self: str, prefix: str, /) -> str:
    if self.startswith(prefix):
        return self[len(prefix):]
    else:
        return self[:]

en welke voordelenhet heeft tegen zelf geïmplementeerde oplossingen:

  1. Minder kwetsbaar:
    De code is niet afhankelijk van de gebruiker om de lengte van een letterlijke waarde te tellen.

  2. Performant:
    De code vereist geen aanroep van de ingebouwde len-functie van Python, noch naar de duurdere str.replace()-methode.

  3. Meer beschrijvend:
    De methoden geven een API op een hoger niveau voor leesbaarheid van de code, in tegenstelling tot de traditionele methode van string slicing.


Antwoord 16

import re
def rm_suffix(url = 'abcdc.com', suffix='\.com'):
    return(re.sub(suffix+'$', '', url))

Ik wil dit antwoord herhalen als de meest expressieve manier om het te doen. Natuurlijk kost het volgende minder CPU-tijd:

def rm_dotcom(url = 'abcdc.com'):
    return(url[:-4] if url.endswith('.com') else url)

Als de CPU echter de bottleneck is, waarom dan in Python schrijven?

Wanneer is CPU eigenlijk een bottleneck? In stuurprogramma’s, misschien.

De voordelen van het gebruik van reguliere expressies zijn herbruikbaarheid van code. Wat als je vervolgens ‘.me’ wilt verwijderen, dat maar drie tekens heeft?

Dezelfde code zou volstaan:

>>> rm_sub('abcdc.me','.me')
'abcdc'

Antwoord 17

In mijn geval moest ik een uitzondering indienen, dus dat deed ik:

class UnableToStripEnd(Exception):
    """A Exception type to indicate that the suffix cannot be removed from the text."""
    @staticmethod
    def get_exception(text, suffix):
        return UnableToStripEnd("Could not find suffix ({0}) on text: {1}."
                                .format(suffix, text))
def strip_end(text, suffix):
    """Removes the end of a string. Otherwise fails."""
    if not text.endswith(suffix):
        raise UnableToStripEnd.get_exception(text, suffix)
    return text[:len(text)-len(suffix)]

Antwoord 18

U kunt split gebruiken:

'abccomputer.com'.split('.com',1)[0]
# 'abccomputer'

Antwoord 19

Een bredere oplossing, met de mogelijkheid om het achtervoegsel te vervangen(je kunt verwijderen door te vervangen door de lege string) en om het maximum aantal vervangingen in te stellen:

def replacesuffix(s,old,new='',limit=1):
    """
    String suffix replace; if the string ends with the suffix given by parameter `old`, such suffix is replaced with the string given by parameter `new`. The number of replacements is limited by parameter `limit`, unless `limit` is negative (meaning no limit).
    :param s: the input string
    :param old: the suffix to be replaced
    :param new: the replacement string. Default value the empty string (suffix is removed without replacement).
    :param limit: the maximum number of replacements allowed. Default value 1.
    :returns: the input string with a certain number (depending on parameter `limit`) of the rightmost occurrences of string given by parameter `old` replaced by string given by parameter `new`
    """
    if s[len(s)-len(old):] == old and limit != 0:
        return replacesuffix(s[:len(s)-len(old)],old,new,limit-1) + new
    else:
        return s

In jouw geval, gegeven de standaardargumenten, wordt het gewenste resultaat verkregen met:

replacesuffix('abcdc.com','.com')
>>> 'abcdc'

Enkele meer algemene voorbeelden:

replacesuffix('whatever-qweqweqwe','qwe','N',2)
>>> 'whatever-qweNN'
replacesuffix('whatever-qweqweqwe','qwe','N',-1)
>>> 'whatever-NNN'
replacesuffix('12.53000','0',' ',-1)
>>> '12.53   '

Antwoord 20

Dit is een perfect gebruik voor reguliere expressies:

>>> import re
>>> re.match(r"(.*)\.com", "hello.com").group(1)
'hello'

Antwoord 21

Hier heb ik een eenvoudigste code.

url=url.split(".")[0]

Antwoord 22

Python >= 3.9:

'abcdc.com'.removesuffix('.com')

Python < 3.9:

def remove_suffix(text, suffix):
    if text.endswith(suffix):
        text = text[:-len(suffix)]
    return text
remove_suffix('abcdc.com', '.com')

Antwoord 23

Vervangen en tellen gebruiken

Dit lijkt misschien een beetje een hack, maar het zorgt ervoor dat u veilig kunt vervangen zonder startswithen als statement, met behulp van de countarg van vervangen, kunt u het vervangen beperken naar één:

mystring = "www.comwww.com"

Voorvoegsel:

print(mystring.replace("www.","",1))

Suffix (je schrijft het voorvoegsel omgekeerd) .comwordt moc.:

print(mystring[::-1].replace("moc.","",1)[::-1])

Antwoord 24

Ik heb de ingebouwde rstripfunctie om het als volgt te doen:

string = "test.com"
suffix = ".com"
newstring = string.rstrip(suffix)
print(newstring)
test

Other episodes