Problem z usuwaniem elementu listy

Problem z usuwaniem elementu listy
E1
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 3 lata
  • Postów:27
0

Witam,
Czy może mi ktoś wytłumaczyć co tu się dzieje, bo ja już nie wiem.

Otóż, jest sobie string sttr oraz jest lista out zawierająca pierwsze litery grup znaków D (digits), P (punctuation), L (lowercase), U (uppercase).
Pętla for ma zadanie, aby z listy usunąć oznaczenia występujących znaków.
W moim stringu występują wszystkie cztery grupy. Jest literka mała, jest literka duża, jest cyferka i znaki specjalne.

Kopiuj
from string import ascii_lowercase, ascii_uppercase, digits, punctuation

sttr = 'Lo$a2@'

out = ['D', 'L', 'P', 'U']

try:
    for i in sttr:
        if i in [x for x in ascii_uppercase]:
            out.remove('U')
        elif i in [x for x in ascii_lowercase]:
            out.remove('L')
        elif i in [x for x in digits]:
            out.remove('D')
        elif i in [x for x in punctuation]:
            out.remove('P')
except ValueError:
    pass

print(out)

I po tym princie z niewiadomych mi powodów otrzymuję to:

Kopiuj
['D']

I nie mam zielonego pojęcia dlaczego tak się dzieje. Wygląda tak, jakby out.remove('D') nie działało.


Komplikowanie jest proste, upraszczanie jest skomplikowane.
ledi12
  • Rejestracja:prawie 6 lat
  • Ostatnio:około 2 miesiące
  • Lokalizacja:Wrocław
1

Wywal try/except to się dowiesz. Kod próbuje usunąć usunięty już element stąd w tym momencie iteracja się wywala (passuje) i reszta skryptu idzie dalej. Jak dasz try/except bezpośrednio w pętli to masz taki fajny kewyord continue, który będzie kontynuował iteracje.

Wywalanie się wynika z tego, że string zawiera dwie małe liter o i a. Przy o triggeruje się elif z out.remove('L') tak samo jak przy a. Z tą różnicą, że przy tej drugiej tego L już nie ma bo został usunięty, więc wywala błąd,

Kopiuj
sttr = 'Lo$a2@'

out = ['D', 'L', 'P', 'U']

for i in sttr:
    try:
        print(i)
        if i in ascii_uppercase:
            out.remove('U')
        elif i in ascii_lowercase:
            out.remove('L')
        elif i in digits:
            out.remove('D')
        elif i in punctuation:
            out.remove('P')
    except ValueError:
        continue
print(out)

Robię http response status cody w martwych ciągach
edytowany 5x, ostatnio: ledi12
E1
try except wstawiłem po to, żeby ValueErrora się pozbyć, jednak jak się okazało, w złym miejscu. Dziękuję za pomoc :)
Spearhead
  • Rejestracja:prawie 6 lat
  • Ostatnio:około godziny
  • Postów:1002
3

Zamiast iterować po znakach możesz po prostu robić operacje na setach:

Kopiuj
from string import ascii_lowercase, ascii_uppercase, digits, punctuation

sttr = 'Lo$a2@'
out = ['D', 'L', 'P', 'U']

str_set = set(sttr)
if str_set & set(digits):
    out.remove('D')
if str_set & set(ascii_lowercase):
    out.remove('L')
if str_set & set(punctuation):
    out.remove('P')
if str_set & set(ascii_uppercase):
    out.remove('U')

print(out)

Jak usuwasz po jednym na raz to nie musisz się martwić, że kiedyś poleci jakiś wyjątek z racji tego, że danej litery w out już nie ma.

edytowany 2x, ostatnio: Spearhead
E1
Słuszna uwaga, dziękuję :)

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.