Iteracja każdego znaku w ciągu za pomocą Pythona


517

W C ++ mogę iterować w następujący sposób std::string:

std::string str = "Hello World!";

for (int i = 0; i < str.length(); ++i)
{
    std::cout << str[i] << std::endl;
}

Jak iterować po ciągu znaków w Pythonie?

Odpowiedzi:


441

Jak zauważył Johannes,

for c in "string":
    #do something with c

Za pomocą for loopkonstruktu możesz iterować prawie wszystko w pythonie ,

na przykład open("file.txt")zwraca obiekt pliku (i otwiera plik), iteracja po nim iteracja po liniach w tym pliku

with open(filename) as f:
    for line in f:
        # do something with line

Jeśli to wydaje się być magią, to w pewnym sensie jest, ale pomysł za tym jest naprawdę prosty.

Istnieje prosty protokół iteratora, który można zastosować do dowolnego obiektu, aby forpętla na nim działała.

Wystarczy zaimplementować iterator, który definiuje next()metodę, i zaimplementuj __iter__metodę na klasie, aby była iterowalna. ( __iter__oczywiście powinien zwrócić obiekt iteratora, czyli obiekt, który definiuje next())

Zobacz oficjalną dokumentację


14
Uwaga: odwrócona iteracja jest archiwizowana za pomocą: for c in
reverse

Z jakiej części dokumentacji wiesz, że łańcuch jest typem iteratora?
winklerrr

dir () string..you z atrybutem see iter .
shadow0359 10.04.17

312

Jeśli potrzebujesz dostępu do indeksu podczas iteracji po ciągu, użyj enumerate():

>>> for i, c in enumerate('test'):
...     print i, c
... 
0 t
1 e
2 s
3 t

9
Wskazówka: zaczyna się od zera. Jeśli musisz uruchomić go z jednym: 1 t, 2 e, 3 s, 4 tużyj parametru "start":for i, c in enumerate('test', start=1)
Messa

90

Jeszcze łatwiej:

for c in "test":
    print c

Jestem nowicjuszem w Pythonie. Z jakiegoś powodu nie kompiluje się w moim środowisku i musiałem umieścić c w nawiasach, aby działało: for c in "test": print (c) Dlaczego?
Mauro Vanetti,

7
@ MauroVanetti to prawie na pewno dlatego, że używasz Python 3, a kiedy odpowiedziałem na pytanie, AFAIK był tylko Python 2.
Johannes Weiss

37

Aby uzyskać bardziej wyczerpującą odpowiedź, w języku Python można zastosować metodę C iteracji po łańcuchu, jeśli naprawdę chcesz zmusić kwadratowy kołek do okrągłego otworu.

i = 0
while i < len(str):
    print str[i]
    i += 1

Ale z drugiej strony, po co to robić, skoro ciągi są z natury iterowalne?

for i in str:
    print i

6
Zamiast pierwszej pętli while możesz zrobić: for i in range (len (str)): print (str [i]) Co moim zdaniem jest lepsze niż samodzielne zarządzanie licznikiem. Jeszcze lepsza jest odpowiedź marcoga za pomocą wyliczenia.
aiham

1
Może to być oparte na tym, że używałem C tak długo, ale prawie zawsze używam tej metody C. Na przykład mam plik z kilkoma 4-cyfrowymi liczbami, z których wszystkie zaczynają się od 0. Więc muszę znaleźć „0” i złapać go i kolejne 3 znaki, i przejść dalej bez duplikowania liczby, jeśli istnieje kolejne 0 po nim. Żadna z metod „for c in str” lub „for i, c in enumerate (str)” nie działa, ponieważ potrzebuję kontroli indeksu. Jestem jednak pewien, że wyrażenie regularne byłoby znacznie lepsze.
gkimsey

1
for i in range(len(...))jest zły. W Pythonie 2.x range()tworzy listę, więc na bardzo dużej długości możesz skończyć przydzielaniem bardzo dużego bloku pamięci. Przynajmniej użyj xrange()w tych przypadkach. Ponadto wielokrotne indeksowanie tego samego łańcucha jest znacznie wolniejsze niż iteracja bezpośrednio nad nim. Jeśli potrzebujesz indeksu, użyj enumerate().
izak

6

Możesz także zrobić coś takiego interesującego i wykonać swoją pracę za pomocą pętli for

#suppose you have variable name
name = "Mr.Suryaa"
for index in range ( len ( name ) ):
    print ( name[index] ) #just like c and c++ 

Odpowiedź to

Pan . Sryaa

Ponieważ jednak range () tworzy listę wartości, która jest sekwencją, więc możesz bezpośrednio użyć nazwy

for e in name:
    print(e)

Daje to również ten sam wynik, a także wygląda lepiej i działa z dowolną sekwencją, taką jak lista, krotka i słownik.

Użyliśmy holowania Wbudowane funkcje (BIF w Python Community)

1) range () - range () BIF służy do tworzenia indeksów Przykład

for i in range ( 5 ) :
can produce 0 , 1 , 2 , 3 , 4

2) len () - len () BIF służy do ustalenia długości danego łańcucha


4

Jeśli chcesz zastosować bardziej funkcjonalne podejście do iteracji po łańcuchu (być może w jakiś sposób go przekształcić), możesz podzielić łańcuch na znaki, zastosować funkcję do każdego z nich, a następnie dołączyć wynikową listę znaków z powrotem do łańcucha.

Ciąg znaków jest z natury listą znaków, dlatego „map” będzie iterował ciąg znaków - jako drugi argument - stosując funkcję - pierwszy argument - do każdego z nich.

Na przykład tutaj używam prostego podejścia lambda, ponieważ wszystko, co chcę zrobić, to trywialna modyfikacja postaci: tutaj, aby zwiększyć wartość każdej postaci:

>>> ''.join(map(lambda x: chr(ord(x)+1), "HAL"))
'IBM'

lub bardziej ogólnie:

>>> ''.join(map(my_function, my_string))

gdzie moja_funkcja przyjmuje wartość char i zwraca wartość char.


2

Wykorzystuje się tutaj kilka odpowiedzi range. xrangejest ogólnie lepszy, ponieważ zwraca generator, a nie listę z pełną instancją. Tam, gdzie problemem może być pamięć i iteracje o bardzo różnych długościach, xrangejest lepsza.


1
zauważ, że dotyczy to tylko Pythona 2, który, jak mam nadzieję, jest obecnie kurczącą się mniejszością
Sam Mason,

0

Jeśli kiedykolwiek spotkasz się z sytuacją, w której musisz get the next char of the word using __next__(), pamiętaj o utworzeniu string_iteratori iteruj nad nim, a nieoriginal string (it does not have the __next__() method)

W tym przykładzie, gdy znajduję znak = [szukam następnego słowa, dopóki go nie znajduję ], więc muszę użyć __next__

tutaj pętla for nad łańcuchem nie pomogłaby

myString = "'string' 4 '['RP0', 'LC0']' '[3, 4]' '[3, '4']'"
processedInput = ""
word_iterator = myString.__iter__()
for idx, char in enumerate(word_iterator):
    if char == "'":
        continue

    processedInput+=char

    if char == '[':
        next_char=word_iterator.__next__()
        while(next_char != "]"):
          processedInput+=next_char
          next_char=word_iterator.__next__()
        else:
          processedInput+=next_char
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.