Kelimeleri Alfabetik Sıralama Fonksiyonumda Tatlı Bir Hata

Arkadaşlar bir listedeki kelimeleri Türkçe diline uygun olarak alfabetik sıralamak için sort,vb metodlar yerine kendi fonksiyonumu yazmak istedim.
Sonuç olarak başardım doğru sıralamayı yapıyorum .
Ancak kodlarımın içerisinde gereksiz tekrarlar yaptığım için uzun girdilerde ( 15 üzeri elemanlı liste)
program sonuca ulaşamıyor)

Sizen ricam gereksiz döngü tekrarı yaptığım varsa başka hatalarımla ilgili dönütlerinizi benimle paylaşmanız.
Kodlarımda açıklamalar ekledim. Kafa yormak isteyenler ,benim gibi takıntılı olanlar ilgilenebilir :slight_smile:

liste=['elma', 'yazılım', 'merhaba', 'muzlar', 'kitap', 'çay', 'ismail', 'muz', 'dost','ılgaz']
alfabe=list(i for i in "abcçdefgğhıijklmnoöprsştuüvyz")## Alfabeyi tanımladım
def alfabetik_siralama(liste):#Fonksiyon başlangıç
    donecek_liste = list()# Yeni liste tanımladım .Bu liste üzerinde ekleme ve yer değişiklikleri yapacağım.Dönecek asıl liste bu
    kontrol = 0 # kontrol değişkeni kaç defa kontrol işlemi gerçekleştirilidiğini saymak ve ileriki durumlarda gereksiz döngüleri tespit etmek için
    for i in range(len(liste)):## ilk listenin elemanlarını almaya başlıyoruz
        if i == 0:## ikinci liste yani donecek_liste boş oluğu için aşağıdaki ilk if bloğunda 'elma'değerini atıyoruz..
            kontrol += 1
            donecek_liste.append(liste[i])
        else:#Asıl tiyatro burada başlıyor donecek_liste boş değil ve artık baştaki listedeki her değeri alıp donecek_liste'deki her değerle kontrol edeceğiz
            for z in range(len(donecek_liste)):#İlk LİSTEDEN gelen kelimeyi ikinci listedeki her değerle eşleştirmek gerekiyor..
                kontrol += 1 # döngülerin çalışma sayılarını alıyorum en sonda doğru sayıda işlem yapıp yapmadığını manuel olarak kontorl etmek için
                uzunluk = min(len(donecek_liste[z]), len(liste[i])) # kıyaslayacağım iki kelimenin uzunlukları önemli çünkü "muz" ve "muzlar" gibi bla bla
                for j in range(uzunluk):# Kısa kelimenin harf sayısı kadar kontrol etmek yeterli bunun için min fonksiyonunu yukarıda kullandım
                    if alfabe.index(donecek_liste[z][j]) < alfabe.index(liste[i][j]):## eğer yeni gelen kelime eski kelimeye göre daha sonra geliyorsa direkt ekleme yapıyorum
                        donecek_liste.append(liste[i])## ekliyoruz
                        break
                    elif alfabe.index(donecek_liste[z][j]) == alfabe.index(liste[i][j]):
                        ## BURADAKİ ELİF BLOĞUNDA kelimelerin harflerinin aynı olma durumu kontrol ediliyor
                        #Ancak kelimelerin uzunluklarının sonuna yani son harfi kontrol ettiysek ve aynıysa 
                        ##'muz' 'muzlar' gibi 2 kelime için kısa olan kelime listede diğer ögenin önüne  ekleniyor
                        print("buraya {} ile {} için {} defa bakıldı".format(donecek_liste[z], liste[i], j + 1))
                        if j == uzunluk - 1:
                            a = len(liste[i]);
                            b = len(donecek_liste[z])
                            if a == b:
                                donecek_liste.append(liste[i])
                            elif a < b:
                                gecici = donecek_liste[z]
                                donecek_liste[z] = liste[i]
                                donecek_liste.append(gecici)
                                break
                            else:
                                donecek_liste.append((liste[i]))
                                break
                    elif alfabe.index(donecek_liste[z][j]) > alfabe.index(liste[i][j]):
                        ## bu blokta yeni gelen kelimenin halihazırda liste[2]'deki kelimenin önüne ekleniyor
                        ## tampon kullandım , insert kullanmayı denedim bazı problemler oldu veyahut ben beceremedim:)
                        gecici = donecek_liste[z]
                        donecek_liste[z] = liste[i]
                        donecek_liste.append(gecici)
                        break
                    else:
                        ##Tüm ihtimalleri yukarıdaki bloklarda hallettim en azından ben öyle varsayıyorum
                        ## Buraya ekleme çıkarmalar yaptığım için tutuyorum:)
                        pass
                    
    ##Asıl sorun burada başlıyor
    ##Normalde en baştaki 10 tane kelimemizi sıralamak istediğimizde aklımdaki algoritmaya göre
    ##Elma kelimesi boş olan dönecek_listesine eklenecek
    ## Ardından gelen yazılım kelimesi sadece elma ile kontrol edilecek
    ## 'MERHABA' 2 KERE
    ## 'MUZLAR' 3 KERE>>
    ## .....    .....
    ## ILGAZ 9 KERE
    ## SONUÇ >> (9*8)/2 = 36 KERE KONTROL ETSE Kİ KAĞIT ÜZERİNDE YAPSAK BU KADAR KONTROL YETERLİ OLUYOR
    ## ANCAK ÇALIŞTIRDIĞINIZDA GÖRECEKSİNİZ 512 TUR DÖNÜYOR ve Bazı DEĞERLERİ bir kaç kez yazıyor
    ##512 KERE DEĞER YAZDIRDIĞI İÇİN AYNI KELİMENİN TEKRARI DURUMLAR OLUYORDU BUNU AŞAĞIDAKİ BLOKLA ÇÖZDÜM
    ## ANCAK BU İŞLEVSEL DEĞİL BENİ FONKSİYONU YAZDIĞIM BÖLÜMDE GEREKSİZ TEKRAR EDEN YERLER VAR VE TESPİT EDEMEDİM
    for i in donecek_liste:
        if donecek_liste.count(i) > 1:
            for j in range(donecek_liste.count(i) - 1):
                donecek_liste.remove(i)
    print(donecek_liste, kontrol, sep="\n")


alfabetik_siralama(liste)

Kodunuz çok uzun biraz kısalttım.

liste = ['elma', 'yazılım', 'merhaba', 'muzlar', 'kitap', 'çay', 'ismail', 'muz', 'dost','ılgaz' ]
harf_degerleri = {
    'a': 1, 'b': 2, 'c': 3, 'ç': 4, 'd': 5, 'e': 6, 'f': 7, 'g': 8, 'ğ': 9, 'h': 10,
    'ı': 11, 'i': 12, 'j': 13, 'k': 14, 'l': 15, 'm': 16, 'n': 17, 'o': 18, 'ö': 19, 'p': 20,
    'r': 21, 's': 22, 'ş': 23, 't': 24, 'u': 25, 'ü': 26, 'v': 27, 'y': 28, 'z': 29
}

sayisal_degerler = list(map(lambda kelime: list(map(lambda harf: harf_degerleri.get(harf.lower(), 0), kelime)), liste))


siralanmis_kelimeler = sorted(zip(liste, sayisal_degerler), key=lambda x: x[1])


for kelime, sayisal_degerler in siralanmis_kelimeler:
    print(f"{kelime}: {sayisal_degerler}")

Bilgisayar Türkçe, ingilizce, almanca bilmez. Bilgisayar rakam bilir.

Harfleriniz alfabelere göre sayısal maplerseniz. Sıralama algoritmalarınızı da bu sayı dizilerini sıralayacak şekilde yazarsanız, her dil için yapmanız gereken tek şey alfabe dizisini sayısal karşılıkta ifade etmektir.

Daha sonra aldığınız kararlara göre sıralama koşulu belirleyip, bubble sort, quick sort, selection sort hangi metodla sıralamak isterseniz o metodla sıralarsınız.

Burada kullandığınız sıralama algoritması size iterasyon sayısı dışında bir fark yaratmayacaktır. İterasyon endişeniz varsa algoritma performanslarına bakar birini seçersiniz.

Son olarak, kodunuz çok uzun okuyup hatası nedir diye bulmak yerine basit bir örnek yazmak daha kolay gibi geldi bana.

Burada sizin istediğiniz kodu yazmadım, sadece bir sıralama algoritması ve bir sayısallaştırma göstermek istedim.

siralanmis_kelimeler = sorted(zip(liste, sayisal_degerler), key=lambda x: x[1])

satırında sıralama sayısal_deger listesine göre yapılır, siz harf olarak yapmak isteseniz x[0] ile sıfır indeksi verip alfabetik olan sıralama ile farkına bakabilirsiniz böylece sayısal sıralama size her zaman kodladığınız alfabeye göre sıralacaktır.

Tabi farklı koşul ve istekleriniz varsa satırı silip kendi sıralama algoritmalarınızı o satırla değiştirebilirsiniz.

Kolay gelsin.

EDIT:

Yukarıdaki kısım zaten komple geresiz döngünün daniskası anlamında bir mesaj idi. Can sıkıntısı hadi bakalım kodu ayıklayıp bir analiz etmeye çalışayım dedim.

Tamam anlıyorum. Tabi ki sıralama algortiması yazmak istemeniz normal lakin optimize edilmiş algoritma yerine kendiniz denemeniz de bir yere kabul edilebilir lakin kafamda deli sorular:

Mesela liste deki eleman sayınız ile aldığınız 512 arasında bir bağıntı var. 2 üzeri n-1,

yani 2 üzeri (10-1) = 2 üzeri 9 = 512 ve her eleman eksiltip denediğimde bu formüle göre değer hesaplaması doğru çıkıyor.

Hele bir kontrol değişkeniniz var bu kontrol değişkeni ile ne hesaplamaya çalıştığınızı hiç anlamadım.

Yani iterasyon sayısı desem j değişkenli for döngüsünde artırmamışsınız sonuçta orada da bir for döngüsüne giriyor.

i ile z yi takip ediyor desem neden böyle bir şey yapmak ister insan onu da anlamadım.

Birinci listeden eksiltip ikinci listeye ekleyerek yapsa desem o da değil. i ile başlayan for döngüsü sürekli 9 a kadar sayıyor.

z döngüsü ap ayrı bir dünya;

z döngüsünde ne yaptınız da z 512’ye kadar gitti diyeceğim, geri doğru taradım baş tarafı daha anlamsız bir halde.

Acaba bende mi problem var deyip, can sıkıntısından chatgpt ye sordum:

Elin delli chatgpt si şunları yazdı:

Bu kod bir liste üzerinde alfabetik sıralama yapmaya çalışıyor gibi görünüyor. Kodun işleyişini analiz edelim:

1. `alfabetik_siralama` adında bir fonksiyon tanımlanmış. Bu fonksiyon bir liste alıyor ve alfabetik sıralanmış bir listeyi döndürmeyi amaçlıyor.

2. `donecek_liste` adında boş bir liste ve `kontrol` adında bir sayı tanımlanıyor.

3. Bir `for` döngüsü kullanarak, `liste`nin elemanlarını tek tek işlemeye başlıyoruz.

4. İlk adımda (`i == 0`), `donecek_liste`'ye `liste`'nin ilk elemanını ekliyoruz ve `kontrol` değişkenini artırıyoruz.

5. İkinci adımda (`i > 0`), `donecek_liste`'deki elemanlarla karşılaştırma yapmak için bir iç içe `for` döngüsü kullanıyoruz.

6. İç içe `for` döngüsünde, `donecek_liste`'nin elemanlarını (`donecek_liste[z]`) `liste`'nin `i`'nci elemanıyla (`liste[i]`) karşılaştırıyoruz.

7. Karşılaştırma yaparken, `alfabe.index()` fonksiyonunu kullanarak harflerin alfabetik sıralamadaki indekslerini karşılaştırıyoruz.

8. Eğer `donecek_liste[z][j]` harfi, `liste[i][j]` harfinden önce geliyorsa, `liste[i]`'yi `donecek_liste`'ye ekliyoruz ve iç içe döngüden çıkıyoruz (`break`).

9. Eğer iki harfin indeksleri eşitse, her iki kelimenin de aynı kısmını karşılaştırıyoruz (`j` değişkeni ile kontrol ediyoruz).

10. Eğer karşılaştırma sonucunda aynı kısma kadar her iki kelime de aynı ise, uzunluğa göre kısa olan kelimeyi `donecek_liste`'de önce yerleştiriyoruz.

11. Eğer `donecek_liste[z][j]` harfi, `liste[i][j]` harfinden sonra geliyorsa, bu durumda `donecek_liste[z]` ile `liste[i]`'yi yer değiştiriyoruz.

12. `else` bloğunda herhangi bir durumun sağlanmadığı durumları kontrol ediyoruz.

13. İç içe döngülerden çıktıktan sonra, `donecek_liste`'deki elemanları tekrar sayarak (`donecek_liste.count()`) eğer bir elemandan birden fazla varsa, fazla olanları silme işlemi yapılıyor (`donecek_liste.remove()`).

14. Son olarak, `donecek_liste` ve `kontrol` değerleri yazdırılıyor.

Kodun bazı eksiklikleri ve

 iyileştirmeleri şunlar olabilir:

- `alfabe` adında bir alfabe dizisi veya liste tanımlanmamış. Bu nedenle, `alfabe.index()` fonksiyonunun nasıl çalıştığına bağlı olarak bu kısım hata verebilir. Alfabe tanımlamasını kodun başına eklemeniz gerekebilir.
- Kodun okunabilirliği ve anlaşılırlığı düşük. Değişken adları ve kod bloklarının daha açıklayıcı olması önemlidir.
- Kodda aşırı döngü kullanımı var, bu da performansı olumsuz etkileyebilir. Daha etkili bir sıralama algoritması kullanarak bu sorunu çözebilirsiniz, örneğin `sorted()` fonksiyonunu kullanabilirsiniz.
- Fonksiyonun sonucunu döndürmesi yerine, doğrudan yazdırıyor. Fonksiyonun bir liste döndürmesi daha kullanışlı olabilir, böylece sonucu başka bir değişkene atayabilir veya başka işlemlerde kullanabilirsiniz.

Bu analizin size yardımcı olması umuduyla! Eğer başka bir sorunuz varsa, sormaktan çekinmeyin.

Söylediklerinin çoğuna katıldım, bu kadar iç içe for döngüsü yazarsa algoritma performansı düşer en çok katıldığım,

Bir diğer söylediği ise, fonksiyon dönüşünde liste versin fonksiyonun içinde print kullanılır mı?

Yani yapay zeka bile bir fonksiyon nasıl tanımlanır de değer döndürebilir nasıl bir mantıkla fonksiyonun içinde liste değeri döndürmek yerine ekrana yazdırılır diye merak etmiş.

Ben de merak ettim açıkcası:

Neyse başta söylemiştim, sıralama algoritmaları çeşit çeşit performans ve güçlü yönlerine göre birini seçebilirdiniz, inanın bu seçtiğinizin adını koyamadım, bubble desem değil, quick sort desem değil, heapsort desem değil, quick sort desem değil.

İlk listeden bir değer çekti isem ilk listem neden 1 azalıp da 9, 8,7 diye azalmıyor da her seferinde 9 döngü dönüyor bilemedim.

Hele z döngüsü 2 nin üsleri şeklinde nasıl şişti anlamadım. Çok daha da ilginci var if lerden kaynaklı olabilir, j ye kaç kez uğradığına bakınca daha da garipsedim.

liste=['elma', 'yazılım', 'merhaba', 'muzlar', 'kitap', 'çay', 'ismail', 'muz', 'dost','ılgaz']

alfabe=list(i for i in "abcçdefgğhıijklmnoöprsştuüvyz")

def alfabetik_siralama(liste):
    donecek_liste = list()
    kontrol = 0 
    for i in range(len(liste)):
        
        if i == 0:
            kontrol += 1
            donecek_liste.append(liste[i])
        else:
            for z in range(len(donecek_liste)):
                kontrol += 1 
                
                uzunluk = min(len(donecek_liste[z]), len(liste[i])) 
                for j in range(uzunluk):
                    
                    
                    if alfabe.index(donecek_liste[z][j]) < alfabe.index(liste[i][j]):
                        donecek_liste.append(liste[i])
                        break
                    elif alfabe.index(donecek_liste[z][j]) == alfabe.index(liste[i][j]):
                        print(" i:{}, z:{}, j:{}, kontrol:{}".format(i, z, j, kontrol))
                        #print("buraya {} ile {} için {} defa bakıldı".format(donecek_liste[z], liste[i], j + 1))
                        if j == uzunluk - 1:
                            a = len(liste[i]);
                            b = len(donecek_liste[z])
                            if a == b:
                                donecek_liste.append(liste[i])
                            elif a < b:
                                gecici = donecek_liste[z]
                                donecek_liste[z] = liste[i]
                                donecek_liste.append(gecici)
                                break
                            else:
                                donecek_liste.append((liste[i]))
                                break
                    elif alfabe.index(donecek_liste[z][j]) > alfabe.index(liste[i][j]):

                        gecici = donecek_liste[z]
                        donecek_liste[z] = liste[i]
                        donecek_liste.append(gecici)
                        break
                    else:

                        pass
                    
    
    #for i in donecek_liste:
    #    if donecek_liste.count(i) > 1:
    #        for j in range(donecek_liste.count(i) - 1):
    #            donecek_liste.remove(i)
    #print(donecek_liste, kontrol, sep="\n")


alfabetik_siralama(liste)

Kodunuzu biraz budadım. Mesela garip çıktı aldığınız fonksiyonun içindeki forlu en alt çıktı alma kısmını yorum satırına değiştirdim.

Sonra, buraya uğradı falan yazan satırınızda durum nedir diye merak ettim.

Burayı da yoruma çevirip,

print(" i:{}, z:{}, j:{}, kontrol:{}".format(i, z, j, kontrol))

Satırı ile uğradığı durumlarda, x, z, j ve kontrol değişkenlerinizin değerlerine baktım. Kodu çalıştıralım;

image

Sizin uğradığını düşündüğünüz yere 16 kere uğramış.

Tamam en içteki z değişkenli for döngüsüne bakalım, if lerden önce bir yere kodumuzu yazalım ki x,z,j ve kontrol değişkenlerinizin tüm durumlarını görelim;

liste=['elma', 'yazılım', 'merhaba', 'muzlar', 'kitap', 'çay', 'ismail', 'muz', 'dost','ılgaz']

alfabe=list(i for i in "abcçdefgğhıijklmnoöprsştuüvyz")

def alfabetik_siralama(liste):
    donecek_liste = list()
    kontrol = 0 
    for i in range(len(liste)):
        
        if i == 0:
            kontrol += 1
            donecek_liste.append(liste[i])
        else:
            for z in range(len(donecek_liste)):
                kontrol += 1 
                
                uzunluk = min(len(donecek_liste[z]), len(liste[i])) 
                for j in range(uzunluk):
                    print(" i:{}, z:{}, j:{}, kontrol:{}".format(i, z, j, kontrol))
                    
                    if alfabe.index(donecek_liste[z][j]) < alfabe.index(liste[i][j]):
                        donecek_liste.append(liste[i])
                        break
                    elif alfabe.index(donecek_liste[z][j]) == alfabe.index(liste[i][j]):
                        
                        #print("buraya {} ile {} için {} defa bakıldı".format(donecek_liste[z], liste[i], j + 1))
                        if j == uzunluk - 1:
                            a = len(liste[i]);
                            b = len(donecek_liste[z])
                            if a == b:
                                donecek_liste.append(liste[i])
                            elif a < b:
                                gecici = donecek_liste[z]
                                donecek_liste[z] = liste[i]
                                donecek_liste.append(gecici)
                                break
                            else:
                                donecek_liste.append((liste[i]))
                                break
                    elif alfabe.index(donecek_liste[z][j]) > alfabe.index(liste[i][j]):

                        gecici = donecek_liste[z]
                        donecek_liste[z] = liste[i]
                        donecek_liste.append(gecici)
                        break
                    else:

                        pass
                    
    
    #for i in donecek_liste:
    #    if donecek_liste.count(i) > 1:
    #        for j in range(donecek_liste.count(i) - 1):
    #            donecek_liste.remove(i)
    #print(donecek_liste, kontrol, sep="\n")


alfabetik_siralama(liste)

Bu sefer ;

print(" i:{}, z:{}, j:{}, kontrol:{}".format(i, z, j, kontrol))

Satırımızı j döngüsü içerisinde if ile kararlar alınmadan hemen önce bir yere aldık ki sonuçta iç içe, x,z ve j ye nasıl giriyor ve hangi değerleri görüyor biz de görelim.

Ve;

512 satırlık yeni durum:

image

z değeriniz nasıl 255’e kadar ulaşabildi?

j değişkenli for döngünüze uğradığında kontrol değişkeninizi 1 artırmıyorsunuz.

yani oraya uğradı ise dahi bunlar ilave edilmiyor peki bu durumda siz neyi sayıyorsunuz kontrol ile?

Sizin için j for döngünüzün başına kontrol+=1 ben ekledim. Yani oraya girdiğinde de sayalım dedim.

Bakın sonuç ne oldu?

image

1035…

Yani döndük başa, iterasyon sayınızı düzgün saymıyorsunuz.

Sıralama algoritmanız en kibar tabirle tuhaf. Ve adını koyamadım.

Bir fonksiyon dönüşünde ekrana yazmaz bir dönüş değeri döndürür sonra o değer ekrana yazdırılacaksa yazdırılır bu şekilde fonksiyon ruhuna aykırı.

listeleri karşılaştırma komutlarını doğru kullanmamışsınız, karşılaştırma komutları ile forlar azaltılabilirdi. Listenizden eleman çektikten sonra yeni listenizi baştan aşağı tekrar tekrar kontrol ederek çığ gibi büyen bir z değişkenli for döngüsüne dönüştürmüşsünüz bunun daha kolay yolu olan sıralama algoritmalarının mantığını hiç anlamamışsınız.

Yine başta söylediğim gibi ana fikri alfabe olsa sayılara kodlarsınız harf sıralama kaygınız ortadan kalkar. Sort kullanmak istemezseniz o tek satırı kendi sıralama fonksiyonunuzla değiştirirsiniz onda da problem yok ama o sıralama fonksiyonu bu sıralama fonksiyonu değil.

Yani evet sıralıyordur ama adımlayıp değerlere bakıyorum bu şekilde çalışan bir kod yazın deseniz yazamam bu karmaşayı ve kaosu yaratmak özel maharet ister.

Onca açıklama satırıyla daha da açıklanamaz ve anlaşılmaz hale getirmeniz de cabası:

#Fonksiyon başlangıç

açıklamanız bomba mesela. Bir fonksiyon def ile tanımlanır diye başlayan bir satır okuyan adam fonksiyon görünce herhalde buradan başlar fonksiyon diyordur, açıklamaya muhtaç görünmüyor.

Diğer yorum satırlarınıza girmiyorum dahi.

Bu şekilde kodunuz daha da okunmaz hale gelmiş. Yorumları silip anlayana kadar göbeğim çatladı.

Python ın kurulu olduğu dizinde bir examples yada demos dizini olacak orada bir sıralama örnek kodu var.

Bence onu bulup bir inceleyin. Sanırım tools/demo dizini altında:

image

Burada bir bar listesi karıştırılıyor sonra sıralama algoritmaları ile sıralanıyor. Hem hız yönünden hem de adım adım sıralamayı görselleştiriyor.

Böylece bir algoritma seçip sizin koda uyarlasınız iyi olur.

Zaten kodunuzda bir şey yok.

bir fonksiyonunuz var o da facia.

Onu çıkarıp başka bir fonksiyon koyunca zaten kod hem okunaklı hem de basit hale geliyor.

Bu nedenle başta zaten kendi kodumu ekledim.

Yine hatırlatıp şu editi kapatayım. Tabi ki bir sıralama algoritmasını kendiniz yazmak isteyebilirsiniz, ama bunu daha iyi yapan optimize bir hazır fonksiyon varken yapacaksanız, sizin daha optimize bir tanesini yazabilecek kadar iyi olduğunuza güvenmeniz gerekir.

Bunca yıldır bende o güven yok mesela, onca sıralama algoritması bilirim kodlarım denerim ama bir dilin yerleşik sıralama yeteneği varsa kendi yazdığımdan çok ona güvenirim.

Ya daha iyisini yapacak kadar öğrenin yada bırakın o işi dilin ilgili fonksiyonu yapsın. Her iki yol için de örnek ve öneri verdim. Burada hunharca eleştirmek için eleştirmedim. Size faydası olacağını düşündüğüm deneyimlerimi aktarmaya çalıştım.

Burada zaten benim kadar yazıp açıklamaya çalışan çok da insan bulamazsın, şurasınız değiştir der zırt giderler hemen, ha öyle istiyorsan benlik bir sorun yok, pass geç benim mesajı diğer yorumculardan devam et.

Tekrar kolay gelsin.

3 Beğeni

Merhaba,

İyi çalışmalar. @semtex’in de dediği gibi karakterlere veya karakter dizilerine sayısal değer ataması yaparak, bu sayısal değerleri küçükten büyüğe sıralayıp sonra da o sayıya veya sayı grubuna karşılık gelen karakteri veya karakter dizisini alabilirsiniz.

Python’da < ve > operatörleri seriler üzerinde de çalışır.

Yani, aşağıdaki iki ifadeyi de çalıştırabilirsiniz ve bu iki ifade de True değerini verir.

print([1.2, 2] > [1.2, 1])
print([1.2, 1] > [1.2, 0, 3])

Ayrıca str sınıfının maketrans ve translate isminde metodları var;

Bu metodlar eşleşim tabloları üretip, bu tablolara göre karakter dönüşümü yapmamızı sağlıyor. Bu eşleştirme yöntemini sorted ile veya kendi yazacağımız sort fonksiyonu ile kullanabiliriz.

Önce sorted, str.maketrans ve str.translate kullanarak sıralama yapalım:

alfabe = "abcçdefgğhıijklmnoöprsştuüvyz"
liste = ['elma', 'yazılım', 'merhaba', 'muzlar', 'kitap', 'çay', 'ismail', 'muz', 'dost', 'ılgaz']
table = str.maketrans({j: index for index, j in enumerate(alfabe)})
print(sorted(liste, key=lambda i: i.translate(table)))
# ['çay', 'dost', 'elma', 'ılgaz', 'ismail', 'kitap', 'merhaba', 'muz', 'muzlar', 'yazılım']

Kendi sort metodumuz ile yapalım şimdi de. Hatta bir tane de min fonksiyonu yazalım ve str.translate ve str.maketrans fonksiyonlarını bu yeni sıralama fonksiyonuna adapte edelim:

def minimum(x: list):
    x_copy = x.copy()
    while len(x_copy) >= 2:
        a, b = (x_copy[1], x_copy[0]) if x_copy[0] > x_copy[1] else (x_copy[0], x_copy[1])
        x_copy.remove(b)
    return x_copy[0]


def sort(x: list, alfabe: dict = None):
    x_sorted = []
    if alfabe:
        table = str.maketrans(alfabe)
        mapping = {i: i.translate(table) for i in x}
        x_copy = [mapping[i] for i in x]
    else:
        mapping = {}
        x_copy = x.copy()
    while x_copy:
        x_min = minimum(x_copy)
        x_sorted += [x_min]
        x_copy.remove(x_min)
    return x_sorted if not alfabe else [{v: k for k, v in mapping.items()}[i] for i in x_sorted]
alfabe = "abcçdefgğhıijklmnoöprsştuüvyz"
liste = ['elma', 'yazılım', 'merhaba', 'muzlar', 'kitap', 'çay', 'ismail', 'muz', 'dost', 'ılgaz']
print(sort(liste, {i: index for index, i in enumerate(alfabe)}))
# ['çay', 'dost', 'elma', 'ılgaz', 'ismail', 'kitap', 'merhaba', 'muz', 'muzlar', 'yazılım']

sort fonksiyonundaki mapping sözlüğü aşağıdaki gibi bir eşleştirme tablosudur:

{'elma': '\x05\x0e\x0f\x00', 'yazılım': '\x1b\x00\x1c\n\x0e\n\x0f', 'merhaba': '\x0f\x05\x14\t\x00\x01\x00', 'muzlar': '\x0f\x18\x1c\x0e\x00\x14', 'kitap': '\r\x0b\x17\x00\x13', 'çay': '\x03\x00\x1b', 'ismail': '\x0b\x15\x0f\x00\x0b\x0e', 'muz': '\x0f\x18\x1c', 'dost': '\x04\x11\x15\x17', 'ılgaz': '\n\x0e\x07\x00\x1c'}

Buradaki her bir anahtarın değeri gördüğünüz gibi str tipinde, yani biz int tipinde bir veri yazdığımız zaman karşımıza bunların 16'lı tabandaki, ancak str notasyonuyla yazılabilen eşdeğerleri çıkıyor. Eğer int tipinde değerler almak istiyorsak, bu str değerlerini decode etmek gerekir. (Bu örnekte decode etmemiz zorunlu değil. Gerek yok. Ama bu 16’lı tabandaki karakter dizisinin hangi sayıları temsil ettiğini bir görelim.)

def decode(x: str):
    return tuple(int(i.encode().hex(), 16) for i in x)

Decode edilmiş değerler şöyle olur:

{'elma': (5, 14, 15, 0), 'yazılım': (27, 0, 28, 10, 14, 10, 15), 'merhaba': (15, 5, 20, 9, 0, 1, 0), 'muzlar': (15, 24, 28, 14, 0, 20), 'kitap': (13, 11, 23, 0, 19), 'çay': (3, 0, 27), 'ismail': (11, 21, 15, 0, 11, 14), 'muz': (15, 24, 28), 'dost': (4, 17, 21, 23), 'ılgaz': (10, 14, 7, 0, 28)}

Bu eşleştirme tablosu oluşturulduktan sonra, liste'deki her bir eleman tuple veya 16’lı tabandaki sayıları içeren bir str nesnesi ile temsil edilebilir artık.

['\x05\x0e\x0f\x00', '\x1b\x00\x1c\n\x0e\n\x0f', '\x0f\x05\x14\t\x00\x01\x00', '\x0f\x18\x1c\x0e\x00\x14', '\r\x0b\x17\x00\x13', '\x03\x00\x1b', '\x0b\x15\x0f\x00\x0b\x0e', '\x0f\x18\x1c', '\x04\x11\x15\x17', '\n\x0e\x07\x00\x1c']

Yukardaki değerlerin decode edilmiş hali şöyle:

[(5, 14, 15, 0), (27, 0, 28, 10, 14, 10, 15), (15, 5, 20, 9, 0, 1, 0), (15, 24, 28, 14, 0, 20), (13, 11, 23, 0, 19), (3, 0, 27), (11, 21, 15, 0, 11, 14), (15, 24, 28), (4, 17, 21, 23), (10, 14, 7, 0, 28)]

Yukardaki listenin uzunluğu orijinal listenin uzunluğu ile aynıdır, ancak mapping'in uzunluğu ile aynı olmayabilir. (Duplicate değerlerimiz varsa, mapping sözlüğü listeden daha küçük olacaktır.)

Artık bu tuple veya 16’lı tabanda sayılar içeren str verilerini kullanarak, elemanları büyüklük-küçüklük ilişkisine göre sıralayabilir sonra da her bir tupleın veya str nesnesinin temsil ettiği karakter dizisine mapping üzerinden ulaşabiliriz.

Yukarda, liste küçükten büyüğe göre şöyle sıralanır:

['\x03\x00\x1b', '\x04\x11\x15\x17', '\x05\x0e\x0f\x00', '\n\x0e\x07\x00\x1c', '\x0b\x15\x0f\x00\x0b\x0e', '\r\x0b\x17\x00\x13', '\x0f\x05\x14\t\x00\x01\x00', '\x0f\x18\x1c', '\x0f\x18\x1c\x0e\x00\x14', '\x1b\x00\x1c\n\x0e\n\x0f']

Yukardaki değerlerin decode edilmiş hali şöyle:

[(3, 0, 27), (4, 17, 21, 23), (5, 14, 15, 0), (10, 14, 7, 0, 28), (11, 21, 15, 0, 11, 14), (13, 11, 23, 0, 19), (15, 5, 20, 9, 0, 1, 0), (15, 24, 28), (15, 24, 28, 14, 0, 20), (27, 0, 28, 10, 14, 10, 15)]

Yukardaki 16’lı tabanda sayılar içeren str veya tuple nesnelerine karşılık gelen karakter dizileri de şunlar olur:

['çay', 'dost', 'elma', 'ılgaz', 'ismail', 'kitap', 'merhaba', 'muz', 'muzlar', 'yazılım']
3 Beğeni

@semtex ve @dildeolupbiten Arkadaşlarım okurken zevk aldım.Elinize emeğinize sağlık çok iyi değerlendirmişsiniz.Çok çok teşekkür ederim.Hem değer verdiğime hem de bazı yerleri not ettiğime emin olabilirisiniz.

Şimdi aslında olay şu ; listedeki kelimeleri alfabetik olarak sıralamayı sort ile denedim ancak gerekli düzenlemeleri tam yapamadığım için i ve ı harfleri problem çıkarıyordu yani i harfi ı harfinden önce geliyordu.
Ben de hem biraz kafa patlatayıp hem de iş güç ara verdiğim için her türlü veri tipini de kullanacağım bir şeyler yazayım dedim.
Plan>> Liste içerisindeki kelimeleri alfabetik olarak sıralama.
Yöntem>> Aklıma sayılarda yaptığımız baloncuk mantığını kurgulamak vardı ancak baloncuk sıralamasında sadece bir önceki değer ile kontrol yeterliydi.Kelimeleri sıralarken ise her kontrol edilecek değeri daha önce listeye eklenmiş tüm kelimelerle sırasıyla kontrol etmem gerekiyordu.
Kabaca tarif etmek gerekirse 4 isim >> efkan,semteks,ali,mehmet
1.Adım ilk kelimeyi boş listeye alıyoruz [efkan]
2.adım semteks kelimesini halihazırdaki efkan ile karşılaştırıp listeye ekliyoruz.
3.adım ali kelimesini listedeki 2 elemanla da karşılaştırıp uygun yere ekliyoruz
4.mehmet kelimesini de 3 elemanla karşılaştırıp uygun yere ekliyoruz.

Yani değerlendirilecek her kelime kendinden önce sıralanmış listedeki tüm değerlerle karşılaştırılıp uygun yere eklensin…
İki kelimeyi karşılaştırırken ise kelime uzunluklarına göre kısa kelimenin boyutunu alıp o kadar sayıda kelimelerin her karakterinin alfabe’deki indeksine göre kelimenin listedeki yerini belirlemek gerekiyordu.
Efkan ve Eftelya için kısa kelime efkan 5 karakter;
maksimum 5 defa iki kelimenin her harfinin alfabedeki indekslerine göre değerlendirecek
E ler ortak devam
f harf ortak devam
K harfi T harfnden önce o zaman Efkan listede önde olacak Eftelyayı listeye ekle
Eğer tam tersi durum söz konusuysa yani yeni gelecek kelime halihazırda bulunan kelimenin önüne geçecekse tampon kullanarak yerlerini değiştir .(inserti burada kullanabilirdim…)

Ancak başlangıçta basit iş yaparım derken, sonuca ulaşma, doğru çıktıyı alma gayesiyle bazı yerleri saçmaladım.Gereksiz değişkenler,döngüler işin içine girdi.Çok fazla ekleme çıkarma yaptım.
Aslında mantık olarak aklımda kruduğum algoritmada herhngi bir problem yoktu ancak bir kaç yerde for döngüsünü fazladan dönderdiğim için aynı kelimeyi fazladan ekleme problemiyle karşılaştım ve bunu da tekrar eden kelimeleri silerek çözdüm :frowning:

Not: Hızlıca sizlerle paylaşmak istedim açıklama kısımlarını birkaç dakika içinde yazdım ama anlaşılamayacak şekilde karmaşık göründüğünü sonradan farkettim :slight_smile:

1 Beğeni

str'yi bir sayı grubuna dönüştürüp, bu sayı grubunu karşılaştırabilirsiniz. İşlem açısından daha az zorlayıcı olacaktır.

Yani aşağıdaki a'yı;

a = "elma"

şöyle temsil edebilirsiniz.

a_temsil = (5, 14, 15, 0)

b de elme olsun.

b = "elme"

b'yi de şöyle temsil edebiliriz:

b_temsil = (5, 14, 15, 5)

Şimdi, a_temsil mi yoksa b_temsil mi küçük sorgusu yapabiliriz.

a = "elma"
a_temsil = (5, 14, 15, 0)
b = "elme"
b_temsil = (5, 14, 15, 5)
if a_temsil > b_temsil:
    print(f"Küçükten büyüğe sıralamada {b}, {a}'dan önce gelmeli.")
else:
    print(f"Küçükten büyüğe sıralamada {a}, {b}'dan önce gelmeli.")

Yukardaki sorgunun sonucunda, Küçükten büyüğe sıralamada elma, elme'dan önce gelmeli. yazısı ekrana yazdırılır.

Özetle, < ve > operatörlerini list, tuple ve str gibi dizilerde kullanabilirsiniz:

Örnek:

print('1.2, 1' > '1.2, 0, 335')

Demek ki burada büyüklük sorgusu str'nin uzunluğuna göre yapılmıyor, str'nin içindeki sayıların büyüklüğüne göre yapılıyor.

Aynı durum diğer iterable yani seri olan, indekselenebilir veri tipleri için de geçerli.

Bu, bizim ne işimize yarar? int > int gibi bir sorgu yapmak yerine iterable > iterable sorgusu yaparak da hangi değerin önce gelmesi gerektiğini bulabiliriz.

3 Beğeni

Çok teşekkür ederim.Dediğiniz yaklaşım ki daha önceki mesajınızda da bahsetmişsiniz sayı olarak karşılaştırma yapmak çok daha mantıklı yol.Sağ olun.

Karşılaştırma elma ile elme arasında da olabilir bu arada.

a = "elma"
b = "elme"
print(b > a)

b, a'dan büyüktür, e, a'dan sonra gelir. Sonra geldiği için, daha yüksek bir sayıyla temsil edilir. Bundan ötürü de b, a'dan büyüktür.

Ama Türkçe karakterler için bunu yapamayız. Çünkü burada a'yı temsil eden sayı ord("a") ile aldığımız sayı. ord("ç"), ord("d")'den çok çok sonra gelir, bu da sıralamanın Türkçe’ye uygun yapılamamasına neden olur. Bunu önlemek için yukardaki örnekte olduğu gibi, alfabenin kendisini referans olarak verip, ona göre harfleri temsil edecek sayıları belirleyebilir ve büyüktür veya küçüktür sorgusuyla sıralama yapabiliriz.

3 Beğeni

Açtığınız sorduğunuz konu güzel olunca üzerinde yaz yaz bitmez.

Hikayeyi bilirsiniz, resmi yapar meydana bırakırsanız ve neresi yanlış çarpı atın derseniz çarpı atan çok olur ama siz bir yanlışı düzeltin deyince pek düzelten olmaz.

Bu nedenle en başta zaten düzeltilmiş bir kod verdim:

siralanmis_kelimeler = sorted(zip(liste, sayisal_degerler), key=lambda x: x[1])

Satırı yerine istediğiniz sıralama fonksiyonunu çağırabilirsiniz.

Ama söylediğim gibi, burada hangi sıralama algoritmasını seçeceğiniz size kalmışken, sıralamada kullanacağınız kuralları bir map ile sayılara çevirmek temel bilgisayar bilimleri yaklaşımdır.

Stringler üzerinde, liseler üzerinde kümeler üzerinde çalışmak arada zaten size ek külfet getirecekti. Bu nedenle temel mantığı önerdik.

Sıralama algoritmasında neden kendi çözümüz üzerinde gitmeyin hazır fonksiyonları kullanın konusunda bir iki ilaveye daha ihtiyaç olduğunu düşünüyorum.

Öncelikle kullandığınız dil python ve python sınıf/object tabanlı bir dil. Yani diğer dillerdeki gibi bakmıyor olaylara, stringler bile python için bir class’tır.

Sınıflar üzerinde çalışan nesne tabanlı bir dilde veri tepleri bile sınıf iken düz yapısal programlama mantığı ile sıralama algoritmaları üretmek doğru bir yaklaşım değildir. (Önerme)

Yani sizin yazdığınız kodun asla sorted() fonksiyonu gibi çalışmasını bekleyemezsiniz. Çünkü sınıf tabanlı ve sınıfların davranışlarına göre gerekli yapıcı ve yıkıcıları içeren belli kurallarla oluşturmuş sınıflar şeklinde tasarlanmış bir komuttur.

Ama siz bu konuda efor sarfetmediniz. sorted() esnektir, farklı sınıf nesneleri üzerinde işlem yapabilir ama size hep liste gelmek zorunda gibi farklılıklar ve kısıtlarınız var.

Başta önerdiğim kodu çalıştıralım:

image

sorted() kodu girdi listeyi, sıraladı.

Büyük küçük harf duyarlı olsa mesela?

Büyük A küçük a dan önce gelecek şekilde ne yapardık?

harf_degerleri = {
    'A: 1, 'a': 2,

gibi listemizi güncellememiz yeterdi. Çünkü hep sayı karşılaştırıyoruz neyi öncelersek o karar geçerli olurdu.

Şimdi sizin yaklaşım listenizdeki dört madde üzerinden ilerleyelim.

1.Adım ilk kelimeyi boş listeye alıyoruz [efkan]
2.adım semteks kelimesini halihazırdaki efkan ile karşılaştırıp listeye ekliyoruz.
3.adım ali kelimesini listedeki 2 elemanla da karşılaştırıp uygun yere ekliyoruz
4.mehmet kelimesini de 3 elemanla karşılaştırıp uygun yere ekliyoruz.

Neden ilk adımda efkan alalım?

Yani elimizde bir liste var ve biz bu listeden aslında ilk seferde ‘ali’ yi çekebiliriz.

Nasıl?

Arama algoritmalarının ilk yaptığı şey de sıralamaktır.

Hiç bilmiyoruz, harf tabanlı çalışmıyoruz, bir işleme girmeden önce neden listemizi uzunluklarına göre sıralamayalım?

Önce uzunluğa göre sılarasak. Sonra her çektiğimiz liste elemanını ilgili verinin önüne mi arkasına mı ekleyeceğiz diye kontrol ederek gidersek?

Yani insertion sort dahil farklı bir çok yaklaşım var performans artırmak için.

Peki yerleştirirsek tüm listeyi baştan sona aramak zorunda mıyız?

Hayır elimizde sıralı bir liste var.

Tek elemanlıysa sıralıdır diye bakabiliriz.

O tek elamandan sonra eklediğimizde listemizin uzadığını düşünelim. Şimdi yeni bir eleman ekleyeceğiz.

Nereden başlarız?

Tam ortasından başlasak?

Elimizdeki kelime orta noktanın sağında mı solunda mı kontrol ederiz.

Sağ ve sol durumu tespit edildikten sonra tekrar sağ yada solun tam ortasına gitsek.

Bu durumu doğru yere kadar tekrar edersek tüm listeyi baştan sona kontrol etmek zorunda kalmayız.

Yani aralıkları her seferinde yarılayarak arama zamanımızı ve adımlarımızı azaltmış olmaz mıyız?

İşte bu nedenle arama algoritması vurgusu yaptım.

Konu uzatılabilir.

Ben de maddeleyim.

  1. Alfabenizi sayılsal haritalayın.
  2. kaynak listenizi isteğe bağlı uzunluklarına göre sıralatın. Gerekli değil ama uzun listelerde optimizasyon sağlayabilir.
  3. Aralık yarılama metodu ile hedef listenizdeki verinin önüne arkasına ekleyin.

Bu bile döngü sayınızı ciddi miktarda azaltacaktır.

Uzunluk yönünden kontrol ederek de zaten içeriklerini fazladan karşılaştırmaktan kurtulmuş olacaksınız.

Konu çok çeşitlendirilebilir.

Söylediğim gibi keyifli bir konu.

Kolay gelsin.

2 Beğeni

Harika fikirleriniz için teşekkürler.Gerçekten farklı bakış açıları ki bunların benim denediklerimden çok daha etkili ve tutarlı olmaları asıl sorunumun dışında yeni fikirler de edinmemi sağladı. Değerli görüşleriniz için çok teşekkür ederim.Saygılar sunuyorum.
@semtex @dildeolupbiten