Forum: Ders Arası RSS
Array içerisinde array kullanımı
Sayfa:  önceki  1  2  3 
acehreli (Moderatör) #31
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj ID 8187
Çok ilginç bir tür olmuş ama çözüm değil:

  • Hep aynı tür olmak zorunda

  • En fazla iki boyutlu tür kullanılabiliyor

İndeksin değer olarak kullanılması da ilginç olmuş. Olası yanlışlıkları gizleyecektir ama belki yararlı kullanımları da vardır.

Ali
Avatar
Salih Dinçer #32
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
acehreli:
İndeksin değer olarak kullanılması da ilginç olmuş. Olası yanlışlıkları gizleyecektir ama belki yararlı kullanımları da vardır.
Yaptığımız iş diziler ile ilgili olduğu için opIndex() kullandım, yoksa aşağıdaki gibi opCall() kullanılırsa köşeli parantezler yerine işlevlerde olduğu gibi parantezli veri girişi yapılabiliyor. Ancak bu da bana garip görünüyor çünkü o bir işlev değil!
  class içİçeDizi(T) {
    union {
      T     x; // tek değerli herhangi bir tür
      T[]   y; // tek boyutlu herhangi bir tür
      T[][] z; // iki boyutlu herhangi bir tür
    }
    T opCall(T t) {
      x = t;
      return x;
    }
    T[] opCall(T[] t...) {
      y = t;
      return y;
    }
    T[][] opCall(T[][] t...) {
      z = t;
      return z;
    }
  }
 
  import std.stdio;
  alias size_t Tür;
  
void main() {
  içİçeDizi!Tür[3] dizi = new içİçeDizi!Tür; {
    "[".write;
    dizi[0]( 1 ).write(", ");
    dizi[1]( 1, 2 ).write(", ");
    dizi[2]( [1, 2, 3], [3, 2, 1] ).writeln("]");
  }
}// Çıktısı: [1, [1, 2], [[1, 2, 3], [3, 2, 1]]] 
Aslında çok daha önemli eksiklikeri var:

Örneğin dolu olan hücreye (elemana) yeni elemanlar ekleyemene. Burada öyle bir şey yok ve hatta hiç parametre girmeyip içeriğini de okuyamıyorsunuz!

Aslında opCall()'ı boş kullanıp bir de ref belirteçi verdiğimizde, artık parametre almadan ve doğrudan değer/dizi gönderek de yapabiliriz. Bu belki hepsinin çözümü olur.

Başarılar...
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Avatar
Salih Dinçer #33
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Şimdi hatırlardım, çıkarsama yapacak veri olmadığı için hata veriyor. Çünkü aşırı yükleme (overload) yapıyoruz.

Denemek isteyen için çalışmayan sınıf:
"ÇALIŞMAYAN KOD":
  class içİçeDizi(T) {
    union {
      T     x; // tek değerli herhangi bir tür
      T[]   y; // tek boyutlu herhangi bir tür
      T[][] z; // iki boyutlu herhangi bir tür
    }
    ref T opCall() { return x; }
    ref T[] opCall() { return y; }
    ref T[][] opCall() { return z; }
  }
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
acehreli (Moderatör) #34
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #32
Salih Dinçer:
Yaptığımız iş diziler ile ilgili olduğu için opIndex() kullandım

Çok doğru yapmışsın. Ama var olmayan indeks değeri bile kullansak kabul ediyor. Dolayısıyla programcının hatasını gizliyor! Programda hata var, yanlış indeks değerleri üretiyoruz buna rağmen sessizce kabul ediyor.

Ayrıca, indeks diye kullanılan değer indeks (yani konum) değil, verinin kendisi olarak kullanılıyor:
    T opIndex(T t) {
      x = t;
      return x;
    }
t'yi veri olarak kullandık. Hani indeksti? Bence bu çok yanıltıcı olur. Herhalde ~ ve ~= işleçleri daha uygun olur. O zaman indeks işlecini gerçekten konum olarak kullanabilirsin.

Belki yanıtı verildi ve ben kaçırdım ama en sonunda bu veriyi nasıl kullanmak istiyoruz? Baştan sona ilerlerken elemanlarla teker teker ne yapmak istiyoruz? T, T dizisi, veya T dizisi dizisi olduklarını nereden bileceğiz?

Ali
Avatar
Salih Dinçer #35
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Merhaba,

Evet, maalesef verinin türüne erişemiyor, geri döndüremiyorum. Ama çok amatörce sınıfa şöyle bir işlev ekledim:
    void tekrarYaz() {   
        if(hangisi == 'x') x.writeln;
        if(hangisi == 'y') y.writeln;
        if(hangisi == 'z') z.writeln;
    }
Bu sayede dizi boyutunu vererek (örn: dizi[1].tekrarYaz;) veri ekrana geliyor. Tabi her işlev içine hangisi'ne bir harf eşitlemek gerekiyor. Dedim ya çok amatörce ama kaput olduğumuzun resmi de! Çünkü ekrana yazılan şeyi tür olarak ana programa geri döndüremiyorum. Adeta kapalı kutu ve bu sınıflar tür bilgisini kendisine saklıyor. Sanki ilk sayfanın sonlarına doğru verdiğim örnekten bir adım öteye gidememişim...:)

Başarılar...
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Avatar
zekeriyadurmus #36
Kullanıcı başlığı: Talha Zekeriya Durmuş
Üye Eki 2012 tarihinden beri · 701 mesaj · Konum: Samsun/Türkiye
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj ID 8187
Tekrardan çok teşekkür ediyorum Salih ve Ali hocam.
Yazdıklarınızı değerlendiriyorum gerçekten çok faydanız oldu bana.

Daha çok visual basic, python, php gibi dillerle uğraştığım için bu veri türleri ve yapıları oldukça karışık geliyor bana açıkcası :)

Bu yüzden anlamam biraz yavaş oluyor kavramlar çok uzak geliyor ama gerçekten faydası oluyor.

Son bir soru daha Associative Arrays için a in b gibi a nın b nin içinde olup olmadığını kontrol edebiliyoruz. Normal arraylar için bunun gibi birşey var mı?
Bilgi meraktan gelir...
acehreli (Moderatör) #37
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
zekeriyadurmus:
gerçekten çok faydanız oldu bana.

Senin sorunun da bize çok faydası oldu. Deneysel alemlere kaydık. :-p

a in b gibi a nın b nin içinde olup olmadığını kontrol edebiliyoruz. Normal arraylar için bunun gibi birşey var mı?

Bu bir arama (find) konusu... Bunun bir çok yolu var.

Eğer dizideki elemanlar baştan sıralanmış iseler, bunun en hızlı yolu ikili aramadır. Şöyle bir kod:
import std.stdio;
import std.range;
import std.algorithm;
import std.random;
 
int[] sıralıDizi(int uzunluk)
{
    return
        iota(0, uzunluk)
        .map!(a => uniform(0, uzunluk))
        .array
        .sort;
}
 
void main()
{
    enum size_t uzunluk = 100;
    auto dizi = sıralıDizi(uzunluk);
 
    /* Elimizde zaten sıralanmış olan bir dizi olduğunda bunu program dilinde
     * ifade etmenin yolu, assumeSorted'ı çağırmaktır. assumeSorted(),
     * SortedRange şablonu döndürür ama tam türünü bilmek zorunda
     * değilizdir. */
    auto kesinSıralıAralık = assumeSorted(dizi);
 
    /* Bazı Phobos algoritmaları SortedRange'i tanıdığından ve böylece
     * aralığın sıralı olduğu kesin bilindiğinden, bu noktadan sonra o
     * algoritmalar daha hızlı işlerler.
     *
     * Bu algoritmalardan birisi equalRange()'dir; verilen kıstasa uyan
     * "ortadaki" aralığı verir: */
    auto aranan = uzunluk / 2;
    {
        writeln("\n--- equalRange() ile ---");
        auto sonuç = kesinSıralıAralık.equalRange(aranan);
 
        if (sonuç.empty) {
            writefln("%s aralıkta bulunamadı", aranan);
 
        } else {
            writefln("Sonuç: %s", sonuç);
        }
    }
 
    /* Dizinin sıralı olup olmadığını bilmiyorsak o zaman dizilerde "sırayla
     * arama" algoritmasını uygulayan find()'ı kullanabiliriz. */
    {
        writeln("\n--- find() ile ---");
        auto sonuç = dizi.find(aranan);
 
        if (sonuç.empty) {
            writefln("%s aralıkta bulunamadı", aranan);
 
        } else {
            writefln("Şu noktada bulundu: %s", sonuç);
        }
    }
}

equalRange()'den başka hızlı algoritmalar da var ama bunlar hep dizinin sıralanmış olmasına dayanıyorlar. (Yani, assumeSorted()'un çağrılmış olması gerek.)

Ali
acehreli (Moderatör) #38
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
acehreli:
bu noktadan sonra o algoritmalar daha hızlı işlerler

Söylemeyi unutmuşum ama sırayla aramanın karmaşıklığı O(N)'dir ve ikili aramanın karmaşıklığı O(log N)'dir. Örneğin, 4 milyar eleman arasında sırayla ararken milyarlarca karşılaştırma gerekirken, ikili aramada 32 karşılaştırma yeter.

Ali
acehreli (Moderatör) #39
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj ID 8162
acehreli on 2012-10-29, 11:33:
    // Kurucu bir veya daha fazla komutla başlayabilir
    this(Komut[] komutlar...)
    {
        /* Not: Burada daha normal olarak şöyle yazabilmek isterdim:
         *
         *     this.komutlar = komutlar;
         *
         * Öyle yapınca program parçalama hatası veriyor çünkü "..." ile
         * işaretlenmiş olan parametre gereğinden erken sonlandırılıyor. Bence
         * öyle olmamalı. Araştıracağım ve gerekirse bir dmd hatası açacağım.
         *
         * Ama ~= işleci çalışıyor:
         */
        this.komutlar ~= komutlar;
    }

Yukarıda neden 'this.komutlar = komutlar' yapılamadığını bugün öğrendim. Bu konu dilin tanımında 'Typesafe Variadic Functions' başlığı altında geçiyormuş:

  http://dlang.org/function.html#variadic

Orada yazdığına göre, belirsiz sayıda parametre alan işlevlere gönderilen parametre değerleri program yığıtında yaşayabilirlermiş ve o yüzden de kısa ömürlü olabilirlermiş:

An implementation may construct the object or array instance on the stack. Therefore, it is an error to refer to that instance after the variadic function has returned:

this.komutlar'ın içine ~= işleci ile eklenmeleri (kopyalanmaları) o yüzden doğru oluyor.

Ali
Avatar
Salih Dinçer #40
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Anlamıyorum...:)

Ben de niye tersi çalışırken, yukarıdaki örnekten çalışan çalışmıyor? Çünkü ben de belirsiz sayıda parametre alıyorum:
  class içİçeDizi(T) {
    union {
      T     x; // tek değerli herhangi bir tür
      T[]   y; // tek boyutlu herhangi bir tür
 
    :    :    :
 
    T[] opCall(T[] t...) {
      y = t;
      return y;
    }
 
    :    :    :
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
acehreli (Moderatör) #41
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Neyi anlamadığını anlamadım. :) Eğer benim çalışmadığını söylediğim sende çalışıyor gibi görünüyorsa tanımsız davranış nedeniyle de olabilir, çağırdığıni yerde hatayı ortaya çıkaracak biçimde çağırmadığın için de olabilir.

Kural açık: Parametre olarak T[] t... diye aldığın diziyi bir üyeye atamak yanlış çünkü o parametreleri oluşturan dizi, program yığıtındaki geçici bir dizi olabilirmiş.

Ama bu sorunu görebilmek için, o işlevi ayrık parametre değerleriyle çağırmak gerekiyor. Örneğin ben şöyle yapmıştım:
ÇokluKomut(new Sil("duzey2_dosya0"),
           new Sil("duzey2_dosya1"));
Dikkat edersen, ÇokluKomut'a bir dizi göndermiyordum. Derleyici iki ayrık nesneden geçici bir dizi oluşturup onu parametre değeri olarak kullanıyormuş.

İşte bu gibi kullanımlar da olabileceği için senin opCall içinde y = t yapman da yanlışmış.

Ali
Doğrulama Kodu: VeriCode Lütfen resimde gördüğünüz doğrulama kodunu girin:
İfadeler: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Özel Karakterler:
Sayfa:  önceki  1  2  3 
Forum: Ders Arası RSS
Bağlı değilsiniz. · Şifremi unuttum · ÜYELİK
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Şu an: 2017-11-21, 12:58:35 (UTC -08:00)