Listeden Döngü İle Eleman Silmedeki Gariplik

Listeler konusunu inceliyorum ve bir iki pratik yaparken aşağıdaki gibi bana garip gelen bir durumla karşılaştım. Liste üzerinde oluşturduğum döngü ile liste elemanlarında koşula uyanları liste içinden remove metodu ile silmek için yazdığım kod çalıştığında koşula uyan liste elemanlarından sonuncusunu silmediğini görüyorum artı çıktıdan anladığım döngünün ilk dönüşünde rastladığı koşula uyan elamanıda silmemiş, silmeye 2.dönüşde başlamış.Ve son dönüşünde de elemana rastlamasına rağmen onu silmeye nedense kıyamamış :smiley: Sebebi konusunda bilgi vermenizi rica ederim.
Sn @dildeolupbiten forumda açılan bir konuda buna benzer bir sorunla karşılaşmış ve durumun kaynağı anlaşılamamış.

liste = ['Doruk', 'Ufuk', 'Oguz', 'Ufuk', 'Ufuk', 'Doruk']
for name in liste:
    if name == 'Ufuk':
        liste.remove(name)
    print(liste)

Screenshot_2

Merhaba,

Bir döngü, liste gibi yinelenebilir bir veri için çalışmaya başladığında, yinelenebilir verinin döngüye girdiği andaki eleman sayısı kadar yineleme gerçekleşir. Ama siz döngü boyunca listenin boyutunu değiştiriyorsunuz ve döngünün tekrarlanma sayısı da bu yüzden düşüyor. Ve listenin eleman sırası da değişiyor.

Döngünün ilk çalışmaya başladığı anda, listenin 0. indisinde Doruk var. Bu ifade koşula uymadığı için silinmeyecek.

Döngünün ikinci adımında, 1. indisteki eleman olan Ufuk'a sıra gelecek. Ve name == "Ufuk" durumu sağlandığı için bu eleman silinecek. Siz bu durumda 1. indisteki elemanı silmiş olacaksınız. Ve listenin boyutunu değiştirdiğiniz için 1. indisindeki eleman bu kez Oguz olacak. Ama Oguz üzerinde bir işlem yapılmayacak. Çünkü 1. indis ile işlem yapılmıştı.

Listenin ikinci indisine ise bu sefer diğer Ufuk gelecek. Döngü, 2. indiste yer alan Ufuk için çalışacak ve bu Ufuk ismini de silecek. Ve bu Ufuk elemanından sonra gelen eleman olan diğer Ufuk ise bu kez listenin yeni 2. indisi olacak. Döngü ikinci indis için daha önce çalıştığı için, bu Ufuk ifadesi silinemeyecek.

Döngü bu kez 3. indis için çalışacak. 3. indiste Doruk var ve Doruk da koşula uymadığı için silinmeyecek.

Ancak kodları şöyle değiştirirseniz, istediğiniz sonucu alırsınız:

liste = ['Doruk', 'Ufuk', 'Oguz', 'Ufuk', 'Ufuk', 'Doruk']
while "Ufuk" in liste:  # Ufuk listenin içinde olduğu sürece
    liste.remove("Ufuk")  # Ufuk'u listeden sil.
print(liste)

Veya bir list comprehension kullanarak, değeri Ufuk olan elemanları listeye dahil etmeyebilirsiniz.

liste = ['Doruk', 'Ufuk', 'Oguz', 'Ufuk', 'Ufuk', 'Doruk']
liste = [i for i in liste if i != "Ufuk"]
3 Beğeni

Allah sizi başımızdan eksik etmesin. Bir çözüm ancak bu kadar açıklayıcı ve öğretme odaklı olabilir. Ayrıca bu çözümler kafam da for ile while arasındaki hangisi nerde daha doğru iş görür sorunsalına da iyi bir örnek teşkil etti zahmet edip bu kadar açıklayıcı yazdığınız için ayrıca tüm acemiler adına tekrar teşekkür ederim.

1 Beğeni

Rica ederim.

while, bir koşul sağlandığı sürece çalışan bir döngü iken, for belirlenmiş bir tekrarlanma sayısı kadar çalışan bir döngüdür (tekrarlanma sayısını değiştiren bir faktör olmadığı sürece). Ama tabi for döngüsünü sonsuza kadar çalıştırmanın yolu da var. Ama böyle bir kullanım için herhangi bir gerekçe şuana kadar hiç görmedim. Ve tavsiye de etmem, çünkü hafızayı, bizim listeye eklediğimiz elemanlar işgal etmiş olur.

Yukarıdaki iki örneğe alternatif olarak öz-yineleme de kullanılabilir. Ancak öz-yinelemenin belli bir sınırı olduğu için, her liste üzerinde başarıyla sonuç vermeyebilir. Bu liste için başarılı bir sonuç alırsınız. Öz-yineleme de bir tür döngüdür.

liste = ['Doruk', 'Ufuk', 'Oguz', 'Ufuk', 'Ufuk', 'Doruk']


def remove(l: list, s: str):
    if s in l:
        l.remove(s)
        return remove(l, s)
    else:
        return l
        
        
print(remove(l=liste, s="Ufuk"))
2 Beğeni
def facto(number):
    if number == 0:
        return 1
    else:
        return number * facto(number-1)
a = int(input(' Enter a number: '))


print(facto(a))

Arin yazılımın videolarını izlerken faktöriyel hesaplama ile ilgili bir örnek yapmıştı ama o videoya kadar böyle bir uygulamaya örnek teşkil edecek bir konudan bahsetmemişti. Bende Konuları belli bir sırada öğrenmeye çalışıyorum daldan dala atlamamak için şu an sayenizde bana kafayı yedirten yahu bu kodda döngü yok
nasıl olur sorusuna bu bir özyinelemeli (söylemesi bana göre çok zor olup kesinlikle TDK tarafından icat edilmiş olduğunu düşündüğüm kelime :smiley) fonksiyon arkadaşım ve özyineleme de bir tür döngüdür diyen bir babayiğit çıkmamıştı. Bu fonksiyon türünün yazbel dökümanlarında başlığı vardı sanırım döngülerle birlikte öğrenilecek bir başlık anladığım kadarıyla onu öğrenmenin sırası gelmiş.

Fonksiyon konusuyla alakalı bir örnek bu. Yani fonksiyonun kendi kendisini çağırması sonucunda bir döngü oluşuyor aslında. Ve bir fonksiyonun kendi kendisini çağırmasının belli bir sınırı var.

Kendi kendini nasıl çağıyor sorusunu sormaktan kendimi alamıyorum şu an…

Herhangi bir fonksiyonun nasıl çağırıldığını öğrenirseniz bunu da anlamış olursunuz.

Bir de Thonny IDE’sini denemek isteyebilirsiniz, özyineleme konusunu güzel görselleştiriyor.

Bu sınır (Recursion Limit) değiştirilebiliyor ama pek de önerilen bir yaklaşım değil, çünkü her fonksiyon çağrımında aslında hafızadaki bir yığın boyutunu (stack size) o fonksiyon için ayırmak zorundasınız. Ve bu da tabi ki yığın aşımı (stackoverlow) sorununu ortaya çıkarır. Yığın aşımı boyutunun da değiştirilebilme imkanı var. Ama buna şimdi hiç girmeyelim. Fakat çok da önerildiğini görmedim.

print(facto(a)) burda bir kere çağırıyor ve ekrana bastırıyoruz tüm bildiğim bu. bu çağrıyı tekrarlatan durumu çözemedim.

Aynı çağırma işlemi fonksiyonun içinde de gerçekleşiyor. Daha önce rastlamadığınız için ilginç gelmesini anlayabiliyorum ama kodun nesini anlamadınız bilmiyorum. İstiyorsanız yukarıda yazdıgım IDE’yi deneyebilir veya İstihza’daki gerekli yeri okuyabilirsiniz.

Aşağıdaki örnek ile aslında bir fonksiyonun kendi kendisini çağırmasının ne olduğunu görebilirsiniz. Genelde, öz-yinelemenin kullanıldığı fonksiyonlarda, öz-yinelemenin durmasını sağlayan bir koşul olur.

def fonk(arguman):  # Parametresi arguman olan bir fonksiyon.
    if len(arguman) == 0:  # Eğer argumanın uzunluğu 0 ise
        return  # None döndür
    else:  # Aksi durumda
        print(arguman[0])  # Argumanın 0. indisini ekrana yazdır.
        return fonk(arguman[1:])  # Listeyi azaltarak fonksiyona argüman 
        # olarak ata ve fonksiyonun kendisini aldığı argüman ile birlikte
        # çağırarak döndür
        
        
fonk([1, 2, 3])

Bu kod, tıpkı aşağıdaki for döngüsü gibi çalışacaktır:

for i in [1, 2, 3]:
    print(i)
1 Beğeni

Bu akşam mutlaka okuyacağım ide’yide ondan sonra denerim teşekkürler.

Hay allah ne muradınız varsa versin tamamdır şimdi anladım.

Kolay gelsin iyi günler.

Asıl sorunun çözümü için şöyle bir şey de yapılabilir:

liste = ['Doruk', 'Ufuk', 'Oguz', 'Ufuk', 'Ufuk', 'Doruk']

i = 0
while i < len(liste):
    if liste[i] == 'Ufuk':
        del liste[i]
    else:
        i += 1

print(liste)
1 Beğeni

Donmekte olan listeyi modifiye etmek iyi bir huy degil. Hic edinmemek en dogrusu. Calisirsa bile cogu dilde kazara calisiyor.

Herhangi bir amaçla yapmadım sadece listelerle ilgili pratik yapıyordum. Uyarınızı dikkate alırım. Teşekkürler