Neler yeni

Yazılım Forum

Tüm özelliklerimize erişmek için şimdi bize katılın. Kayıt olduktan ve giriş yaptıktan sonra konu oluşturabilecek, mevcut konulara yanıt gönderebilecek, itibar kazanabilecek, özel mesajlaşmaya erişebilecek ve çok daha fazlasını yapabileceksiniz! Bu hizmetlerimiz ise tamamen ücretsiz ve kurallara uyulduğu sürece sınırsızdır, o zaman ne bekliyorsunuz? Hadi, sizde aramıza katılın!

Ruby'de Enumerable Modülü: Koleksiyonlarla Etkin Çalışma Sanatı

Ruby'de Enumerable Modülü: Koleksiyonlarla Etkin Çalışma Sanatı

Giriş

Ruby, geliştiricilere güçlü ve esnek araçlar sunan bir dildir. Bu araçlardan belki de en temel ve güçlü olanlarından biri Enumerable modülüdür. Bu modül, koleksiyonlarla (diziler, hash'ler, aralıklar vb.) çalışmayı inanılmaz derecede kolaylaştıran ve kodun okunabilirliğini artıran bir dizi ortak yöntem sunar. Kısacası, Enumerable modülü Ruby'deki birçok sınıfın koleksiyonlara yönelik ortak davranışları paylaşmasını sağlayan bir "mix-in"dir. Bu derinlemesine rehberde, Enumerable modülünün temel felsefesini, en sık kullanılan yöntemlerini, kendi sınıflarınıza nasıl dahil edebileceğinizi ve günlük programlama görevlerinizde size nasıl yardımcı olabileceğini keşfedeceğiz.

“Kodu tekrar etmeyin.” DRY (Don't Repeat Yourself) prensibi, Enumerable modülünün arkasındaki itici güçlerden biridir. Aynı döngü mantığını defalarca yazmak yerine, Enumerable size bu işi zaten yapan metotlar sunar.

Enumerable Modülünün Temel Felsefesi: `each` Metodu

Enumerable modülünün kalbinde `each` metodu yatar. Bu modülü içeren herhangi bir sınıfın, kendi öğeleri üzerinde nasıl tekrarlandığını tanımlayan bir `each` metoduna sahip olması gerekir. Örneğin, Array ve Hash sınıfları Enumerable modülünü içerir ve kendi `each` uygulamalarına sahiptirler.

Kod:
[b]Array örneği:[/b]
meyveler = ["elma", "armut", "kiraz"]
meyveler.each do |meyve|
  puts meyve
end
# Çıktı:
# elma
# armut
# kiraz

[b]Hash örneği:[/b]
notlar = { "Ali" => 90, "Veli" => 85, "Ayşe" => 95 }
notlar.each do |isim, notu|
  puts "#{isim}: #{notu}"
end
# Çıktı:
# Ali: 90
# Veli: 85
# Ayşe: 95

Siz `each` metodunu bir kez tanımladığınızda, Enumerable modülü size onlarca güçlü koleksiyon işleme metodunu ücretsiz olarak sunar. Bu, gerçekten inanılmaz bir verimlilik artışıdır!

Yaygın Enumerable Metotları ve Kullanımları

Enumerable modülü, koleksiyonlar üzerinde karmaşık işlemleri tek satırda yapmanızı sağlayan birçok güçlü metod sunar. İşte en sık kullanılan ve en faydalı olanlardan bazıları:

  • map (veya collect): Bir koleksiyondaki her öğeyi dönüştürerek yeni bir dizi oluşturur.
  • select (veya find_all): Belirli bir koşulu sağlayan öğeleri içeren yeni bir dizi oluşturur.
  • reject: Belirli bir koşulu sağlamayan öğeleri içeren yeni bir dizi oluşturur (select'in tam tersi).
  • find (veya detect): Belirli bir koşulu sağlayan ilk öğeyi döndürür.
  • reduce (veya inject): Bir koleksiyonun öğelerini tek bir değere indirger (toplama, çarpma vb.).
  • sort_by: Belirli bir kritere göre öğeleri sıralar.
  • group_by: Belirli bir kritere göre öğeleri gruplar ve bir Hash döndürür.
  • all?: Tüm öğelerin belirli bir koşulu sağlayıp sağlamadığını kontrol eder.
  • any?: Herhangi bir öğenin belirli bir koşulu sağlayıp sağlamadığını kontrol eder.
  • none?: Hiçbir öğenin belirli bir koşulu sağlayıp sağlamadığını kontrol eder.
  • one?: Yalnızca bir öğenin belirli bir koşulu sağlayıp sağlamadığını kontrol eder.
  • min, max, minmax: Koleksiyondaki en küçük, en büyük veya her ikisini bulur.
  • take, drop: Koleksiyonun başından belirli sayıda öğe alır veya atar.

Şimdi bu metotların bazılarını örneklerle inceleyelim:

1. `map` (veya `collect`)

`map` metodu, bir koleksiyondaki her öğeyi alır, üzerinde bir blok çalıştırır ve bloğun döndürdüğü sonuçlarla yeni bir dizi oluşturur.

Kod:
sayılar = [1, 2, 3, 4, 5]
kareler = sayılar.map { |sayı| sayı * sayı }
puts kareler.inspect
# Çıktı: [1, 4, 9, 16, 25]

isimler = ["ali", "veli", "ayşe"]
büyük_harfli_isimler = isimler.collect(&:upcase) # Sembol proc kullanımı
puts büyük_harfli_isimler.inspect
# Çıktı: ["ALI", "VELI", "AYŞE"]

2. `select` (veya `find_all`)

`select` metodu, belirli bir koşulu (bloğun true döndürdüğü) sağlayan tüm öğeleri içeren yeni bir dizi oluşturur.

Kod:
sayılar = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
çift_sayılar = sayılar.select { |sayı| sayı.even? }
puts çift_sayılar.inspect
# Çıktı: [2, 4, 6, 8, 10]

öğrenciler = [
  { isim: "Ali", not: 85 },
  { isim: "Veli", not: 50 },
  { isim: "Ayşe", not: 92 },
  { isim: "Fatma", not: 60 }
]
geçen_öğrenciler = öğrenciler.find_all { |öğrenci| öğrenci[:not] >= 60 }
puts geçen_öğrenciler.inspect
# Çıktı: [{:isim=>"Ali", :not=>85}, {:isim=>"Ayşe", :not=>92}, {:isim=>"Fatma", :not=>60}]

3. `reject`

`reject` metodu, `select`'in tam tersidir; bloğun true döndürdüğü öğeleri *hariç tutarak* yeni bir dizi oluşturur.

Kod:
sayılar = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
tek_sayılar = sayılar.reject { |sayı| sayı.even? }
puts tek_sayılar.inspect
# Çıktı: [1, 3, 5, 7, 9]

4. `find` (veya `detect`)

`find` metodu, belirli bir koşulu sağlayan *ilk* öğeyi döndürür. Eğer hiçbir öğe koşulu sağlamazsa `nil` döndürür.

Kod:
ürünler = [
  { id: 1, ad: "Laptop", fiyat: 1200 },
  { id: 2, ad: "Fare", fiyat: 25 },
  { id: 3, ad: "Klavye", fiyat: 75 }
]
pahalı_ürün = ürünler.find { |ürün| ürün[:fiyat] > 1000 }
puts pahalı_ürün.inspect
# Çıktı: {:id=>1, :ad=>"Laptop", :fiyat=>1200}

yok_ürün = ürünler.detect { |ürün| ürün[:fiyat] > 5000 }
puts yok_ürün.inspect
# Çıktı: nil

5. `reduce` (veya `inject`)

`reduce` metodu, bir koleksiyonun öğelerini tek bir değere indirger. Bu, bir toplam hesaplamak, bir string birleştirmek veya karmaşık bir indirgeme işlemi yapmak için kullanılabilir.

Kod:
sayılar = [1, 2, 3, 4, 5]
toplam = sayılar.reduce(0) { |akümülatör, sayı| akümülatör + sayı }
puts "Toplam: #{toplam}"
# Çıktı: Toplam: 15

çarpım = sayılar.inject(1) { |akümülatör, sayı| akümülatör * sayı }
puts "Çarpım: #{çarpım}"
# Çıktı: Çarpım: 120

cümle = ["Merhaba", "dünya", "Ruby", "ile"]
birleşik_cümle = cümle.reduce("") { |s, kelime| s + " " + kelime }.strip
puts birleşik_cümle.inspect
# Çıktı: "Merhaba dünya Ruby ile"

`reduce` metodu başlangıç değeri olmadan da kullanılabilir. Bu durumda, koleksiyonun ilk öğesi başlangıç değeri olarak kullanılır.

Kod:
sayılar = [1, 2, 3, 4, 5]
toplam_başlangıç_sız = sayılar.reduce { |akümülatör, sayı| akümülatör + sayı }
puts "Başlangıçsız Toplam: #{toplam_başlangıç_sız}"
# Çıktı: Başlangıçsız Toplam: 15

6. `sort_by`

`sort_by` metodu, bir koleksiyonu belirli bir kritere göre sıralanmış yeni bir dizi olarak döndürür.

Kod:
kişiler = [
  { isim: "Ayşe", yaş: 30 },
  { isim: "Mehmet", yaş: 25 },
  { isim: "Zeynep", yaş: 35 }
]
yaşa_göre_sıralı = kişiler.sort_by { |kişi| kişi[:yaş] }
puts yaşa_göre_sıralı.inspect
# Çıktı: [{:isim=>"Mehmet", :yaş=>25}, {:isim=>"Ayşe", :yaş=>30}, {:isim=>"Zeynep", :yaş=>35}]

ismet_gore_sirali = kişiler.sort_by { |kisi| kisi[:isim] }
puts ismet_gore_sirali.inspect
# Çıktı: [{:isim=>"Ayşe", :yaş=>30}, {:isim=>"Mehmet", :yaş=>25}, {:isim=>"Zeynep", :yaş=>35}]

7. `group_by`

`group_by` metodu, koleksiyonun öğelerini belirli bir kritere göre gruplayarak bir Hash döndürür. Hash'in anahtarları gruplama kriterinin sonuçları, değerleri ise o gruba ait öğelerden oluşan dizilerdir.

Kod:
öğrenciler = [
  { isim: "Ali", cinsiyet: "erkek", not: 85 },
  { isim: "Veli", cinsiyet: "erkek", not: 50 },
  { isim: "Ayşe", cinsiyet: "kadın", not: 92 },
  { isim: "Fatma", cinsiyet: "kadın", not: 60 }
]

cinsiyete_göre_gruplanmış = öğrenciler.group_by { |öğrenci| öğrenci[:cinsiyet] }
puts cinsiyete_göre_gruplanmış.inspect
# Çıktı:
# {"erkek"=>[{:isim=>"Ali", :cinsiyet=>"erkek", :not=>85}, {:isim=>"Veli", :cinsiyet=>"erkek", :not=>50}],
#  "kadın"=>[{:isim=>"Ayşe", :cinsiyet=>"kadın", :not=>92}, {:isim=>"Fatma", :cinsiyet=>"kadın", :not=>60}]}

geçme_durumuna_göre_gruplanmış = öğrenciler.group_by { |öğrenci| öğrenci[:not] >= 60 ? "Geçti" : "Kaldı" }
puts geçme_durumuna_göre_gruplanmış.inspect
# Çıktı:
# {"Geçti"=>[{:isim=>"Ali", :cinsiyet=>"erkek", :not=>85}, {:isim=>"Ayşe", :cinsiyet=>"kadın", :not=>92}, {:isim=>"Fatma", :cinsiyet=>"kadın", :not=>60}],
#  "Kaldı"=>[{:isim=>"Veli", :cinsiyet=>"erkek", :not=>50}]}

8. `all?`, `any?`, `none?`, `one?`

Bu metotlar, bir koleksiyonun öğelerinin belirli bir koşulu sağlayıp sağlamadığını kontrol eden boolean (doğru/yanlış) değer döndüren metotlardır.

Kod:
sayılar = [2, 4, 6, 8, 10]
puts "Tümü çift mi? #{sayılar.all?(&:even?)}" # Çıktı: Tümü çift mi? true

sayılar_karışık = [1, 2, 3, 4, 5]
puts "Herhangi biri çift mi? #{sayılar_karışık.any?(&:even?)}" # Çıktı: Herhangi biri çift mi? true

puts "Hiçbiri tek mi? #{sayılar.none?(&:odd?)}" # Çıktı: Hiçbiri tek mi? true

puts "Sadece bir tanesi 3 mü? #{sayılar_karışık.one? { |s| s == 3 }}" # Çıktı: Sadece bir tanesi 3 mü? true
puts "Sadece bir tanesi 100 mü? #{sayılar_karışık.one? { |s| s == 100 }}" # Çıktı: Sadece bir tanesi 100 mü? false

Enumerable'ı Kendi Sınıflarınıza Dahil Etme

Kendi özel koleksiyon sınıfınızı oluşturduğunuzda, Enumerable modülünü `include` ederek Ruby'nin sunduğu tüm bu güçlü metotlardan yararlanabilirsiniz. Tek yapmanız gereken, sınıfınızda öğeler üzerinde nasıl tekrarlandığını tanımlayan bir `each` metodu uygulamaktır.

Kod:
class MyCollection
  include Enumerable

  def initialize(elements)
    @elements = elements
  end

  def each
    @elements.each do |element|
      yield element # Bloğu her öğe için çağır
    end
  end

  # Ek olarak bir metot daha ekleyelim:
  def add_element(element)
    @elements << element
  end
end

koleksiyon = MyCollection.new([10, 20, 30, 40, 50])

puts "Tüm öğeler: "
koleksiyon.each { |e| puts e }

puts "İki katı: #{koleksiyon.map { |e| e * 2 }.inspect}"
puts "30'dan büyükler: #{koleksiyon.select { |e| e > 30 }.inspect}"
puts "Toplam: #{koleksiyon.reduce(:+)}"

koleksiyon.add_element(60)
puts "Yeni toplam: #{koleksiyon.reduce(:+)}" # 210

Bu örnekte, `MyCollection` sınıfı `Enumerable`'ı içerdiği ve kendi `each` metodunu uyguladığı için, `map`, `select`, `reduce` gibi Enumerable metotlarını otomatik olarak kazanmıştır. Bu, kod tekrarını önler ve daha temiz, daha anlaşılır bir tasarım sağlar.

Performans Notları ve İpuçları

Enumerable metotları genellikle performansı optimize etmek için iyi tasarlanmıştır. Ancak, çok büyük veri kümeleriyle çalışırken dikkat etmeniz gereken bazı noktalar vardır:

* Zincirleme Metotlar: Birçok Enumerable metodunu ardı ardına zincirlemek yaygın bir kullanımdır. Ancak, her zincirleme çağrısı yeni bir dizi oluşturabilir. Örneğin, `array.map(...).select(...)` ifadesi iki yeni dizi oluşturur. Eğer performans kritikse ve büyük dizilerle çalışıyorsanız, bir tek döngüde daha az geçiş yaparak aynı işlemi gerçekleştirecek manuel bir döngü yazmayı düşünebilirsiniz. Ancak çoğu durumda, Enumerable'ın okunabilirliği performans maliyetine değer.
* Lazy Enumerable: Ruby 2.0 ile birlikte gelen "Lazy Enumerable" özelliği, sonsuz veya çok büyük koleksiyonlar üzerinde çalışırken performansı büyük ölçüde artırabilir. `enum.lazy` çağrısı ile Enumerable metodlarını tembel (lazy) hale getirebilirsiniz, bu da işlemlerin sadece gerektiğinde yapılmasını sağlar.

Kod:
# Normal kullanımda performans sorunu:
(1..Float::INFINITY).map { |i| i * 2 }.first(5) # Hata: sonsuz döngü

# Lazy Enumerable ile:
lazy_sayılar = (1..Float::INFINITY).lazy.map { |i| i * 2 }.first(5)
puts lazy_sayılar.inspect
# Çıktı: [2, 4, 6, 8, 10]

Sonuç

Ruby'deki Enumerable modülü, koleksiyonlarla çalışırken olmazsa olmaz bir araçtır. `each` metodunu uygulayarak, otomatik olarak elde ettiğiniz zengin metot seti sayesinde daha az kod yazarak daha fazlasını yapabilirsiniz. Kodunuz daha kısa, daha okunabilir ve daha sürdürülebilir hale gelir. Bu modülün derinlemesine anlaşılması, her Ruby geliştiricisinin beceri setinde bulunması gereken temel bir yetenektir.

Daha fazla bilgi için Ruby'nin resmi belgelerini ziyaret edebilirsiniz: Ruby-Doc: Enumerable Module.
Enumerable modülü, fonksiyonel programlama prensiplerini Ruby'de uygulamanın harika bir yolunu sunar. Bu modülü ustaca kullanmak, kodunuzu daha etkili, daha modüler ve daha zevkli hale getirecektir. Unutmayın, iyi bir yazılımcı sadece ne yapacağını değil, aynı zamanda bunu en zarif ve etkin şekilde nasıl yapacağını da bilir. Enumerable tam da bu kapıyı aralar.
 
shape1
shape2
shape3
shape4
shape5
shape6
Üst

Bu web sitenin performansı Hazal Host tarafından sağlanmaktadır.

YazilimForum.com.tr internet sitesi, 5651 sayılı Kanun’un 2. maddesinin 1. fıkrasının (m) bendi ve aynı Kanun’un 5. maddesi kapsamında Yer Sağlayıcı konumundadır. Sitede yer alan içerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır.

YazilimForum.com.tr, kullanıcılar tarafından paylaşılan içeriklerin doğruluğunu, güncelliğini veya hukuka uygunluğunu garanti etmez ve içeriklerin kontrolü veya araştırılması ile yükümlü değildir. Kullanıcılar, paylaştıkları içeriklerden tamamen kendileri sorumludur.

Hukuka aykırı içerikleri fark ettiğinizde lütfen bize bildirin: lydexcoding@gmail.com

Sitemiz, kullanıcıların paylaştığı içerik ve bilgileri 6698 sayılı KVKK kapsamında işlemektedir. Kullanıcılar, kişisel verileriyle ilgili haklarını KVKK Politikası sayfasından inceleyebilir.

Sitede yer alan reklamlar veya üçüncü taraf bağlantılar için YazilimForum.com.tr herhangi bir sorumluluk kabul etmez.

Sitemizi kullanarak Forum Kuralları’nı kabul etmiş sayılırsınız.

DMCA.com Protection Status Copyrighted.com Registered & Protected