Python'da bir dizenin sonundan bir alt dizeyi nasıl kaldırabilirim?


382

Takip koduna sahibim:

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

Tahmin etmiştim: abcdc

Bende var: abcd

Şimdi yapıyorum

url.rsplit('.com', 1)

Daha iyi bir yol var mı?


6
şerit dizenin her iki ucundan verilen karakterleri, sizin durumunuzda ".", "c", "o" ve "m" harflerini sıyırır.
truppo

6
Ayrıca bu karakterleri dizenin önünden de kaldıracaktır. Sadece sonuna kadar kaldırmak istiyorsanız, rstrip () kullanın
Andre Miller

42
Evet. str.strip ne düşündüğünü yapmıyor. str.strip, dizenin başından ve sonundan belirtilen karakterleri siler. Yani, "acbacda" .strip ("ad") 'cbac' verir; başında a ve sonunda da soyulmuş. Şerefe.
scvalex

2
Ayrıca, bu karakterler herhangi bir sırayla kaldırılır : "site.ocm"> "site".
Eric O Lebigot

1
@scvalex, wow bunu yaşları boyunca bu şekilde kullandığını fark etti - tehlikeli çünkü kod genellikle yine de çalışıyor
Flash

Yanıtlar:


556

strip"bu alt dizeyi kaldır" anlamına gelmez. bir karakter kümesi gibi x.strip(y)davranır yve o kümedeki tüm karakterleri uçlarından ayırır x.

Bunun yerine şunları kullanabilir endswithve dilimleyebilirsiniz:

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

Veya düzenli ifadeler kullanarak :

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

4
Evet, bence endwith () testi ile ilk örnek daha iyi olacaktı; normal ifade bir performans cezası içerecektir (normal ifadeyi ayrıştırma vb.). Ben rsplit () bir ile gitmek olmaz, ama tam olarak ne elde etmeye çalıştığını bilmiyorum çünkü. Ben sadece ve url sonunda görünüyorsa .com kaldırıyorum anlamaya? 'Www.commercialthingie.co.uk' gibi etki alanı adlarında kullanırsanız, rsplit çözümü size sorun çıkarır
Steef

13
url = url[:-4] if any(url.endswith(x) for x in ('.com','.net')) else url
Burhan Khalid

1
ne yazma eğer EXAMLPLE.COMalan adları harf duyarlı değildir. (Bu normal ifade çözümü için bir oy)
Jasen

3
Bu bir yeniden yazma rsplit()değildir endswith(), orijinal dize sonunda alt dizeye sahip değilken, ortada bir yerde çözümle aynı davranışa sahip değildir. Örneğin: "www.comeandsee.com".rsplit(".com",1)[0] == "www.comeandsee"ama"www.comeandsee.net".rsplit(".com",1)[0] == "www"
Steef

1
Sözdiziminin s[:-n]bir uyarısı vardır: çünkü n = 0, bu son sıfır karakteri kesilmiş olarak dizeyi değil, bunun yerine boş dizeyi döndürür.
BlenderBender

90

Dizenin yalnızca sonunda göründüğünden eminseniz, en basit yol 'replace' kullanmaktır:

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

56
URL'nin yerini alacak www.computerhope.com. kontrol edin endswith()ve iyi olmalı.
ghostdog74

72
"www.computerhope.com".endswith(".com")doğru, hala kırılacak!

1
"Dizenin yalnızca sonunda göründüğünden eminseniz" "Alt dizenin yalnızca bir kez göründüğünden eminseniz" demek istiyor musunuz? replace, alt dize ortadayken de işe yarıyor gibi görünüyor, ancak diğer yorumda alt dize herhangi bir oluşumun yerini alacak, neden anlamamalıyım
idclev 463035818 22:02

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

4
Son ekin boş olmadığını biliyorsanız (sabit olduğunda olduğu gibi): dönüş metni [: - len (sonek)]
MarcH

4
Teşekkürler. Son satır kısaltılabilir:return text[:-len(suffix)]
Jabba

3
@Jabba: Ne yazık ki, fuenfundachtzig'in de belirttiği gibi, boş ekler için işe yaramayacak.
yairchu

46

Henüz kimse bunu işaret etmediği için:

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

split()Yeni liste nesnesi oluşturulmadığından, bu yöntemlerden daha verimli olmalıdır ve bu çözüm birkaç noktalı dizelerde çalışır.


Vay canına, bu güzel bir numara. Bunu başarısızlığa uğratamadım ama bunun başarısız olabileceği yolları düşünebilmekte de zorlandım. Sevdim ama çok "büyülü", sadece ona bakarak bunun ne yaptığını bilmek zor. "Anlamak" için çizginin her bir parçasını zihinsel olarak işlemem gerekiyordu.
DevPlayer

14
Aranan dize DEĞİL, bu başarısız olur ve bunun yerine son karakteri yanlış kaldırır.
robbat2

25

URL'niz hakkında bildiklerinize ve tam olarak ne yapmaya çalıştığınıza bağlıdır. Her zaman '.com' (veya '.net' veya '.org') ile biteceğini biliyorsanız, o zaman

 url=url[:-4]

en hızlı çözümdür. Daha genel bir URL ise, muhtemelen python ile gelen urlparse kütüphanesine bakmanız daha iyidir.

Öte yandan, finalden sonra her şeyi kaldırmak istersiniz. o zaman bir dizede

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

çalışacak. Ya da sadece her şeyi ilk '' e kadar istiyorsanız. o zaman dene

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

16

Bunun bir uzantı olduğunu biliyorsanız,

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

Bu ile eşit derecede iyi çalışır abcdc.comya www.abcdc.comya abcdc.[anything]ve daha genişletilebilir.


12

Bir satırda:

text if not text.endswith(suffix) or len(suffix) == 0 else text[:-len(suffix)]


7

Url'ler için (verilen örnekte konunun bir parçası gibi göründüğü gibi), böyle bir şey yapılabilir:

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)

Her ikisi de çıktı verecektir: ('http://www.stackoverflow', '.com')

Bu, str.endswith(suffix)yalnızca ".com" u veya belirli bir şeyi bölmeniz gerektiğinde de birleştirilebilir .


5

url.rsplit ('. com', 1)

tam olarak doğru değil.

Aslında yazmanız gereken şey

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

ve oldukça özlü görünüyor IMHO.

Ancak, kişisel tercihim yalnızca bir parametre kullandığı için bu seçenektir:

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

1
+1 bölümü, her zaman bir yanıt döndürdüğü için yalnızca bir bölme gerektiğinde tercih edilir, bir IndexError oluşmaz.
Gringo Suave


2

Eğer varsa bir dizenin bir ucunu soymanız gerekiyorsa, aksi takdirde hiçbir şey yapmayın. En iyi çözümlerim. Muhtemelen ilk 2 uygulamadan birini kullanmak isteyeceksiniz, ancak tamlık için 3.'ü ekledim.

Sabit bir sonek için:

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'

Normal ifade için:

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"

Sürekli soneklerin toplanması için, çok sayıda çağrı için asimptotik olarak en hızlı yol:

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

sonuncusu muhtemelen pypy'den sonra cpython'dan önemli ölçüde daha hızlıdır. Normal ifade değişkeni, en azından cPython'da kolayca normal ifade olarak gösterilemeyen potansiyel soneklerin büyük sözlüklerini içermeyen neredeyse tüm durumlarda bundan daha hızlıdır.

PyPy'de regex varyantı, çok sayıda çağrı veya uzun teller için neredeyse kesinlikle daha yavaştır, çünkü re modülü, lambda yükünün büyük çoğunluğu JIT tarafından optimize edileceği için bir DFA derleme regex motoru kullanıyor olsa bile.

Bununla birlikte, cPython'da regex için çalışan c kodunuzun neredeyse tüm durumlarda sonek toplama sürümünün algoritmik avantajlarını neredeyse kesinlikle karşılaştırması gerçeği.


2

Yalnızca uzantıyı kaldırmak istiyorsanız:

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

Herhangi bir uzantı ile çalışır, dosya adında da potansiyel diğer noktalar vardır. Dizeyi noktalar üzerinde bir liste olarak böler ve son öğe olmadan birleştirir.


2
import re

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

Bu cevabı yapmanın en etkileyici yolu olarak tekrarlamak istiyorum. Tabii ki, aşağıdakiler daha az CPU zamanı alacaktır:

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

Ancak, CPU şişe boynu ise neden Python yazmalısınız?

CPU ne zaman bir şişe boynu? Sürücülerde, belki.

Düzenli ifade kullanmanın avantajları kodun yeniden kullanılabilirliği. Daha sonra yalnızca üç karakteri olan '.me' öğesini kaldırmak isterseniz ne olur?

Aynı kod hile yapar:

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

1

Benim durumumda bir istisna oluşturmam gerekiyordu, bu yüzden yaptım:

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)]


1

Etki alanı ne olursa olsun (.com, .net vb.) Kaldırmak istediğinizi varsayarsak. .Bu noktadan itibaren her şeyi bulmanızı ve kaldırmanızı öneririm .

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

Burada , adının azaltılması rfindgibi URL'lerin sorununu çözmek için kullanıyorum .abcdc.com.netabcdc.com

Ayrıca www.s konusunda endişeleriniz varsa , bunları açıkça kontrol etmelisiniz:

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

Yerine gelen 1 gibi garip edgecases içindir www.net.www.com

URL'niz bundan daha vahşi olursa, insanların yanıtladığı normal yanıtlara bakın.


1

Takip etmek için dahili rstrip işlevini kullandım:

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

Kötü bir fikir. Deneyin "test.ccom".
Shital Shah

Ancak sorunun konusu bu değil. Sadece bilinen bir alt dizeyi diğerinin sonundan çıkarması istendi. Bu tam olarak beklendiği gibi çalışır.
Alex

1

Split kullanabilirsiniz:

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

5
Ne zaman a = 'www.computerbugs.com'bu sonuçlar 'www'
yairchu

0

Bu düzenli ifadeler için mükemmel bir kullanımdır:

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

5
Ayrıca , ".com" ile biten ana makine adlarını eşleştirdiğinizden emin olmak için bir $ eklemeniz gerekir .
Cristian Ciupitu

0

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

1
Python 3.9'a verdiğiniz yanıt, yukarıdaki bu cevabın bir kopyasıdır . Önceki sürümler için yanıtınız da bu iş parçacığında birçok kez yanıtlanmıştır ve dizenin soneki yoksa hiçbir şey döndürmez.
Xavier Guihot
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.