16 Aralık 2019 Pazartesi

Karakter Dizilerini Alfabe Sırasına Dizmek

Python’da karakter dizilerinin öğelerine tek tek ulaşma, öğeleri dilimleme ve ters çevirmenin yanısıra, bu öğeleri alfabe sırasına dizmek de mümkündür. Bunun için sorted() adlı bir fonksiyondan yararlanacağız:
>>> sorted("kitap")

['a', 'i', 'k', 'p', 't']
Nasıl input() fonksiyonu çıktı olarak bir karakter dizisi ve len() fonksiyonu bir sayı veriyorsa, sorted() fonksiyonu da bize çıktı olarak, birkaç bölüm sonra inceleyeceğimiz ‘liste’ adlı bir veri tipi verir.
Ama tabii eğer isterseniz bu çıktıyı alıştığınız biçimde alabilirsiniz:
print(*sorted("kitap"), sep="")
...veya:
for i in sorted("kitap"):
    print(i, end="")
Bir örnek daha verelim:
>>> sorted("elma")

['a', 'e', 'l', 'm']
Gördüğünüz gibi, sorted() fonksiyonunu kullanmak çok kolay, ama aslında bu fonksiyonun önemli bir problemi var. Dikkatlice bakın:
>>> sorted("çiçek")

['e', 'i', 'k', 'ç', 'ç']
Burada Türkçe bir karakter olan ‘ç’ harfinin düzgün sıralanamadığını görüyoruz. Bu sorun bütün Türkçe karakterler için geçerlidir.
Bu sorunu aşmak için şöyle bir yöntem deneyebilirsiniz:
>>> import locale
>>> locale.setlocale(locale.LC_ALL, "Turkish_Turkey.1254") #Windows için
>>> locale.setlocale(locale.LC_ALL, "tr_TR") #GNU/Linux için
>>> sorted("çiçek", key=locale.strxfrm)

['ç', 'ç', 'e', 'i', 'k']
Burada locale adlı bir modülden yararlandık. locale de tıpkı sysos ve keyword gibi bir modül olup, içinde pek çok değişken ve fonksiyon barındırır.
locale modülü bize belli bir dilin kendine has özelliklerine göre programlama yapma imkanı verir. Örneğin bu modülünün içinde yer alan fonksiyonlardan biri olan setlocale() fonksiyonunu kullanarak, programımızda öntanımlı dil ayarlarına uygun bir şekilde programlama yapma olanağı sağlarız.
Bu modülü ilerleyen derslerde daha ayrıntılı bir şekilde inceleyeceğiz. O yüzden locale modülünü bir kenara bırakıp yolumuza devam edelim.
Yukarıdaki örnekte Türkçe karakterleri doğru sıralayabilmek için sorted() fonksiyonunu nasıl kullandığımıza dikkat edin:
>>> sorted("çiçek", key=locale.strxfrm)
Burada sorted() metodunun key adlı özel bir parametresine locale.strxfrm değerini vererek Türkçeye duyarlı bir sıralama yapılmasını sağladık. Yukarıdaki yöntem pek çok durumda işinize yarar. Ancak bu yöntem tek bir yerde işe yaramaz. Dikkatlice bakın:
>>> sorted("afgdhkıi", key=locale.strxfrm)

['a', 'd', 'f', 'g', 'h', 'i', 'ı', 'k']
Gördüğünüz gibi, bu yöntem ‘i’ harfini ‘ı’ harfinden önce getiriyor. Halbuki Türk alfabesine göre bunun tersi olmalıydı. Buna benzer problemlerle İngiliz alfabesi dışındaki pek çok alfabede karşılaşırsınız. Dolayısıyla bu sadece Türkçeye özgü bir sorun değil.
Bu soruna karşı şöyle bir kod da yazabilirsiniz:
>>> harfler = "abcçdefgğhıijklmnoöprsştuüvyz"
>>> çevrim = {i: harfler.index(i) for i in harfler}
>>> sorted("afgdhkıi", key=çevrim.get)

['a', 'd', 'f', 'g', 'h', 'ı', 'i', 'k']
Gördüğünüz gibi burada ilk iş olarak Türk alfabesindeki bütün harfleri harfler adlı bir değişkene atadık. Daha sonra ise şöyle bir kod yazdık:
>>> çevrim = {i: harfler.index(i) for i in harfler}
Burada henüz öğrenmediğimiz bir yapı var, ama ne olup bittiğini daha iyi anlamak için bu çevrim değişkeninin içeriğini kontrol etmeyi deneyebilirsiniz:
>>> print(çevrim)

{'ğ': 8, 'ı': 10, 'v': 26, 'g': 7, 'ş': 22, 'a': 0, 'c': 2, 'b': 1, 'e': 5,
'd': 4, 'ç': 3, 'f': 6, 'i': 11, 'h': 9, 'k': 13, 'j': 12, 'm': 15, 'l': 14,
'o': 17, 'n': 16, 'p': 19, 's': 21, 'r': 20, 'u': 24, 't': 23, 'ö': 18,
'y': 27, 'z': 28, 'ü': 25}
Bu çıktıya dikkatlice bakarsanız, her bir harfin bir sayıya karşılık gelecek şekilde birbiriyle eşleştirildiğini göreceksiniz. Mesela ‘ğ’ harfi 8 ile, ‘f’ harfi 6 ile eşleşmiş. Yine dikkatlice bakarsanız, biraz önce bize sorun çıkaran ‘ı’ harfinin 10, ‘i’ harfinin ise 11 ile eşleştiğini göreceksiniz. Evet, doğru tahmin ettiniz. Harfleri sayılarla eşleştirerek, Python’ın harfler yerine sayıları sıralamasını sağlayacağız. Bunu da yine key parametresini kullanarak yapıyoruz:
>>> sorted("afgdhkıi", key=çevrim.get)
Bu yapıyı daha iyi anlayabilmek için kendi kendinize bazı denemeler yapın. Eğer burada olan biteni anlamakta zorlanıyorsanız hiç endişe etmeyin. Bir-iki bölüm sonra bunları da kolayca anlayabilecek duruma geleceksiniz. Bizim burada bu bilgileri vermekteki amacımız, Python’ın Türkçe harflerle sıralama işlemini sorunsuz bir şekilde yapabileceğini göstermektir. Bu esnada bir-iki yeni bilgi kırıntısı da kapmanızı sağlayabildiysek kendimizi başarılı sayacağız.

Karakter Dizileri Üzerinde Değişiklik Yapmak

Bu kısımda karakter dizilerinin çok önemli bir özelliğinden söz edeceğiz. Konumuz karakter dizileri üzerinde değişiklik yapmak. İsterseniz neyle karşı karşıya olduğumuzu anlayabilmek için çok basit bir örnek verelim.
Elimizde şöyle bir karakter dizisi olduğunu düşünün:
>>> meyve = "elma"
Amacımız bu karakter dizisinin ilk harfini büyütmek olsun.
Bunun için dilimleme yönteminden yararlanabileceğimizi biliyorsunuz:
>>> "E" + meyve[1:]

'Elma'
Burada “E” harfi ile, meyve değişkeninin ilk harfi dışında kalan bütün harfleri birleştirdik.
Bir örnek daha verelim.
Elimizde şöyle dört adet internet sitesi adresi olsun:
site1 = "www.google.com"
site2 = "www.istihza.com"
site3 = "www.yahoo.com"
site4 = "www.gnu.org"
Bizim amacımız bu adreslerin her birinin baş tarafına http:// ifadesini eklemek. Bunun için de yine karakter dizisi birleştirme işlemlerinden yararlanabiliriz. Dikkatlice inceleyin:
site1 = "www.google.com"
site2 = "www.istihza.com"
site3 = "www.yahoo.com"
site4 = "www.gnu.org"

for i in site1, site2, site3, site4:
    print("http://", i, sep="")
Eğer www. kısımlarını atmak isterseniz karakter dizisi birleştirme işlemleri ile birlikte dilimleme yöntemini de kullanmanız gerekir:
for i in site1, site2, site3, site4:
    print("http://", i[4:], sep="")
Belki farkındayız, belki de değiliz, ama aslında yukarıdaki örnekler karakter dizileri hakkında bize çok önemli bir bilgi veriyor. Dikkat ettiyseniz yukarıdaki örneklerde karakter dizileri üzerinde bir değişiklik yapmışız gibi görünüyor. Esasında öyle de denebilir. Ancak burada önemli bir ayrıntı var. Yukarıdaki örneklerde gördüğümüz değişiklikler kalıcı değildir. Yani aslında bu değişikliklerin orijinal karakter dizisi üzerinde hiçbir etkisi yoktur. Gelin isterseniz bunu teyit edelim:
>>> kardiz = "istihza"
>>> "İ" + kardiz[1:]

'İstihza'
Dediğimiz gibi, sanki burada “istihza” karakter dizisini “İstihza” karakter dizisine çevirmişiz gibi duruyor. Ama aslında öyle değil:
>>> print(kardiz)

istihza
Gördüğünüz gibi, kardiz değişkeninin orijinalinde hiçbir değişiklik yok. Ayrıca burada "İ" + kardiz[1:] satırı ile elde ettiğiniz sonuca tekrar ulaşmanızın imkanı yok. Bu değişiklik kaybolmuş durumda. Peki bunun sebebi nedir?
Bunun nedeni, karakter dizilerinin değiştirilemeyen (immutable) bir veri tipi olmasıdır. Python’da iki tür veri tipi bulunur: değiştirilemeyen veri tipleri (immutable datatypes) ve değiştirilebilen veri tipleri (mutable datatypes). Bizim şimdiye kadar gördüğümüz veri tipleri (sayılar ve karakter dizileri), değiştirilemeyen veri tipleridir. Henüz değiştirilebilen bir veri tipi görmedik. Ama birkaç bölüm sonra değiştirilebilen veri tiplerini de inceleyeceğiz.
Neyse... Dediğimiz gibi, karakter dizileri üzerinde yaptığımız değişikliklerin kalıcı olmamasını nedeni, karakter dizilerinin değiştirilemeyen bir veri tipi olmasıdır. Python’da bir karakter dizisini bir kez tanımladıktan sonra bu karakter dizisi üzerinde artık değişiklik yapamazsınız. Eğer bir karakter dizisi üzerinde değişiklik yapmanız gerekiyorsa, yapabileceğiniz tek şey o karakter dizisini yeniden tanımlamaktır. Mesela yukarıdaki örnekte kardiz değişkeninin tuttuğu karakter dizisini değiştirmek isterseniz şöyle bir kod yazabilirsiniz:
>>> kardiz = "İ" + kardiz[1:]
>>> print(kardiz)

İstihza
Burada yaptığımız şey kardiz değişkeninin değerini değiştirmek değildir. Biz burada aslında bambaşka bir kardiz değişkeni daha tanımlıyoruz. Yani ilk kardiz değişkeni ile sonraki kardiz değişkeni aynı şeyler değil. Bunu teyit etmek için önceki derslerimizde gördüğümüz id() fonksiyonundan yararlanabilirsiniz:
>>> kardiz = "istihza"
>>> id(kardiz)

3075853248

>>> kardiz = "İ" + kardiz[1:]
>>> id(kardiz)

3075853280
Gördüğünüz gibi, ilk kardiz değişkeni ile sonraki kardiz değişkeni farklı kimlik numaralarına sahip. Yani bu iki değişken bellek içinde farklı adreslerde tutuluyor. Daha doğrusu, ikinci kardiz, ilk kardiz‘i silip üzerine yazıyor.
Her ne kadar kardiz = "İ" + kardiz[1:] kodu kardiz‘in değerini aslında değiştirmiyor olsa da, sanki kardiz değişkeninin tuttuğu karakter dizisi değişiyormuş gibi bir etki elde ediyoruz. Bu da bizi memnun etmeye yetiyor...
Yukarıdaki örnekte karakter dizisinin baş kısmı üzerinde değişiklik yaptık. Eğer karakter dizisinin ortasında kalan bir kısmı değiştirmek isterseniz de şöyle bir şey yazabilirsiniz:
>>> kardiz = "istihza"
>>> kardiz = kardiz[:3] + "İH" + kardiz[5:]
>>> kardiz

'istİHza'
Gördüğünüz gibi, yukarıdaki kodlarda karakter dizilerini dilimleyip birleştirerek, yani bir bakıma kesip biçerek istediğimiz çıktıyı elde ettik.
Mesela ilk örnekte kardiz değişkeninin ilk karakteri dışında kalan kısmını (kardiz[1:]) “İ” harfi ile birleştirdik ("İ" + kardiz[1:]").
İkinci örnekte ise kardiz değişkeninin ilk üç karakterine “İH” ifadesini ekledik ve sonra buna kardiz değişkeninin 5. karakterinden sonraki kısmını ilave ettik.
Karakter dizileri üzerinde değişiklik yapmanızın hangi durumlarda gerekli olacağını gösteren bir örnek daha verip bu konuyu kapatalım.
Diyelim ki, bir kelime içindeki sesli ve sessiz harfleri birbirinden ayırmanız gereken bir program yazıyorsunuz. Yani mesela amacınız ‘istanbul’ kelimesi içinde geçen ‘i’, ‘a’ ve ‘u’ harflerini bir yerde, ‘s’, ‘t’, ‘n’, ‘b’ ve ‘l’ harflerini ise ayrı bir yerde toplamak. Bunun için şöyle bir program yazabilirsiniz:
sesli_harfler = "aeıioöuü"
sessiz_harfler = "bcçdfgğhjklmnprsştvyz"

sesliler = ""
sessizler = ""

kelime = "istanbul"

for i in kelime:
    if i in sesli_harfler:
        sesliler += i
    else:
        sessizler += i

print("sesli harfler: ", sesliler)
print("sessiz harfler: ", sessizler)
Burada öncelikle şu kodlar yardımıyla Türkçedeki sesli ve sessiz harfleri belirliyoruz:
sesli_harfler = "aeıioöuü"
sessiz_harfler = "bcçdfgğhjklmnprsştvyz"
Ardından da, sesli ve sessiz harflerini ayıklayacağımız kelimedeki sesli harfler ve sessiz harfler için boş birer karakter dizisi tanımlıyoruz:
sesliler = ""
sessizler = ""
Programımız içinde ilgili harfleri, o harfin ait olduğu değişkene atayacağız.
Kelimemiz “istanbul”:
kelime = "istanbul"
Şimdi bu kelime üzerinde bir for döngüsü kuruyoruz ve kelime içinde geçen herbir harfe tek tek bakıyoruz. Kelime içinde geçen harflerden, sesli_harfler değişkeninde tanımlı karakter dizisinde geçenleri sesliler adlı değişkene atıyoruz. Aksi durumda ise, yani kelime içinde geçen harflerden, sessiz_harfler değişkeninde tanımlı karakter dizisinde geçenleri, sessizler adlı değişkene gönderiyoruz:
for i in kelime:
    if i in sesli_harfler:
        sesliler += i
    else:
        sessizler += i
Bunun için for döngüsü içinde basit bir ‘if-else’ bloğu tanımladığımızı görüyorsunuz. Ayrıca bunu yaparken, sesliler ve sessizler adlı değişkenlere, for döngüsünün her bir dönüşünde yeni bir harf gönderip, bu değişkenleri, döngünün her dönüşünde yeni baştan tanımladığımıza dikkat edin. Çünkü, dediğimiz gibi, karakter dizileri değiştirilemeyen veri tipleridir. Bir karakter dizisi üzerinde değişiklik yapmak istiyorsak, o karakter dizisini baştan tanımlamamız gerekir.


Kaynaklar:
Başer, M. "Python Programlama Dili." İstanbul: Pusula Yayınnları (2001).
https://belgeler.yazbel.com/python-istihza/

Hiç yorum yok:

Yorum Gönder

Karakter Dizilerini Alfabe Sırasına Dizmek Python’da karakter dizilerinin öğelerine tek tek ulaşma, öğeleri dilimleme ve ters çevirmenin...