Thread overview
GBS-3: Yetenekli Chunks() ile Telefon Tuşları
Jan 15, 2022
Salih Dincer
Jan 15, 2022
Salih Dincer
Jan 15, 2022
Ali Çehreli
Jan 16, 2022
Salih Dincer
Jan 17, 2022
Ferhat Kurtulmuş
Jan 17, 2022
Salih Dincer
January 15, 2022

Merhaba,

Bu sabah, şu başlıkta yetenekli chunks() ile tanıştım. Eğer kendisine dizi verirseniz, parçalı aralığa veya isteğe bağlı ve kolayca diziye çevirebilirsiniz. Üstelik sadece dizi değil aralık da alıyor!

Peki ne yapıyor?

İlk parametre olarak ister aralık (rangeNum) verin isterseniz dizi (arrayNum), verdiğiniz ikinci parametreye göre (bu değer, parça adeti değil her parçanın max. uzunluğu) bölüyor:

import std;

void main() {
  auto arrayNum = 1.iota(10).array;

  typeid(arrayNum).writeln(": ", arrayNum);
//int[]: [1, 2, 3, 4, 5, 6, 7, 8, 9]

  auto phoneKeys = arrayNum.chunks(3).array;
  phoneKeys.writefln!"%(%s\n%)";
  "[*, 0, #]".writeln; // EVET, KOLAYA KAÇTIM :)

// #2
  auto rangeNum = 1.iota(10);

  typeid(rangeNum).writeln(": ", rangeNum);
//std.range.iota!(int, int).iota.Result: [1, 2, 3, 4, 5, 6, 7, 8, 9]

  phoneKeys = rangeNum.chunks(3).map!array.array;
  phoneKeys.writefln!"%(%s\n%)";
  "[*, 0, #]".writeln; // EVET, KOLAYA KAÇTIM :)
}/* ÇIKTISI:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
[*, 0, #]
*/

Farketmişsinizdir, örneğin 2. bölümünde aralık verdiğimiz için devamını map'lemeden diziye çeviremiyoruz! Ama bu sefer veriyi işlemek adına daha çok olanağa sahip olabiliriz.

Kolay gelsin...

January 15, 2022

Yukarısı hakikaten GBS idi, ya buna ne demeli:

import std;

void main() {
  auto iller = ["Adana","Adıyaman","Afyon", "Ağrı",
                "Amasya","Ankara","Antalya","Artvin",
                "Aydın","Balıkesir","Bilecik","Bingöl",
                "Bitlis","Bolu","Burdur","Bursa"];

  // 2. karakteri benziyorsa gruplandırır:
  foreach(grup; iller.chunkBy!
         ((a,b) => a[1] == b[1])
  ) if(grup.array.length > 1) {
    grup.writeln;
  }

  // Son karakteri benziyorsa gruplandırır:
  foreach(grup; iller.chunkBy!
         ((a,b) => a[$-1] == b[$-1])
  ) if(grup.array.length > 1) {
    grup.writeln;
  }
}

Bir de chunkBy varmış! Mutlaka deneyin çok güzel bir örnek!

Başarılar...

January 15, 2022
On 1/15/22 01:49, Salih Dincer wrote:

>    ) if(grup.array.length > 1) {

'array' hevesle dizi oluşturan bir algoritmadır. Salt grubun uzunluğunu bulmak için dizi oluşturmak bazı durumlarda aşırı masraflı olabilir.

Dizi oluşturmak deyince perde arkasında bir kaç kere bellek ayırmak, eleman kopyalamak, gerektiğinde taşımak gibi işlemler olduğunu akılda tutmak gerek. Üstelik, aralıkların en çekici taraflarından birisi tembellikleri (yani, yalnızca gerektikçe iş yapmaları) olunca bir döngü içinde dizi oluşturmak masraflı görünüyor.

Onun dışında, evet, Phobos'un aralık algoritmalarını çok kullanışlı buluyoruz.

Bu kullanımda .array.length yerine .count yazmak aynı sonucu verdi ama bellek ayırma sayısı çok azaldı.

Kodun ilk hali:

------------------------
bytes allocated, allocations, type, function, file:line
            736	             23 std.array.Appender!(immutable(char)[][]).Appender.Data std.array.Appender!(string[]).Appender.this /usr/include/dlang/dmd/std/array.d:3330
            368	              1	immutable(char)[][] D main deneme.d:178
------------------------

.count ile değiştirilmiş hali:

------------------------
bytes allocated, allocations, type, function, file:line
            368	              1	immutable(char)[][] D main deneme.d:178
------------------------

Yukarıdaki sonuçları programı `dmd -profile=gc ...` diye derleyerek buldum. Derledikten sonra programı çalıştırınca bulunduğumuz klasöre profilegc.log adında bir dosya bırakıyor.

Son olarak, foreach döngülerinin o çok özel parantez yerlerini ve hatta küme parantezi kullanmıyor olmalarını farkettiğimi söylemek isterim. ;)

Ali

January 16, 2022

On Saturday, 15 January 2022 at 23:36:22 UTC, Ali Çehreli wrote:

>

Son olarak, foreach döngülerinin o çok özel parantez yerlerini ve hatta küme parantezi kullanmıyor olmalarını farkettiğimi söylemek isterim. ;)

Haklısınız hocam :)

Şimdi yeni öğrediklerim sayesinde if de uçtu:

foreach(grup; iller.chunkBy!
         ((a,b) => a[1] == b[1]).
         filter!(r => r.count > 1))
{
  grup.writeln;
}
January 17, 2022

On Sunday, 16 January 2022 at 07:50:31 UTC, Salih Dincer wrote:

>

On Saturday, 15 January 2022 at 23:36:22 UTC, Ali Çehreli wrote:

>

Son olarak, foreach döngülerinin o çok özel parantez yerlerini ve hatta küme parantezi kullanmıyor olmalarını farkettiğimi söylemek isterim. ;)

Haklısınız hocam :)

Şimdi yeni öğrediklerim sayesinde if de uçtu:

foreach(grup; iller.chunkBy!
         ((a,b) => a[1] == b[1]).
         filter!(r => r.count > 1))
{
  grup.writeln;
}

foreach de kaldırılabilir. Ama bence kod okunabilirliğini azaltıyor.

iller.chunkBy!((a,b) => a[1] == b[1]).filter!(r => r.count > 1).each!(arr => arr.writeln);

January 17, 2022

On Monday, 17 January 2022 at 08:14:17 UTC, Ferhat Kurtulmuş wrote:

>

foreach de kaldırılabilir. Ama bence kod okunabilirliğini azaltıyor.

Kesinlikle! Ama UFCS'de insanın hoşuna giden bir taraf var. Sanırım her şeyde olduğu gibi ölçüsüz davranmamak gerekiyor. Hani insanoğlunun bir huyu vardır ya aşırıya kaçma yönünde! Belki o zaman (programlama araçlarınını dengeli kullanarak), daha okunaklı ve her manasıyla verimli kodlar yazılabilir.

İnanmayacaksınız! Tam bilgisayarı açmış ve Community/Forum bağlantısına tıklıyorken yanlışlıkla sürükle bırak yapıp ana sayfaya geçtim. Pufff nidalarıyla aynı işlemi tekrar edecektim ki "dur bir dakika" dedim kendi kendime! Ana sayfada konuyla alakalı şu örneği gördüm:

    import std.algorithm, std.stdio
    import std.file, std.range;

    enum cols = 14;

void main()
{
    // Split file into 14-byte chunks per row
    thisExePath.File("rb").byChunk(cols).take(20).each!(chunk =>
        // Use range formatting to format the
        // hexadecimal part and align the text part
        writefln!"%(%02X %)%*s  %s"(
            chunk,
            3 * (cols - chunk.length), "", // Padding
            chunk.map!(c => // Replace non-printable
                c < 0x20 || c > 0x7E ? '.' : char(c))));
}

Aslında tek satırlık (ikiye bölersek, veriyi okuyup parçalama ve biçimli şekilde ekrana yazma) kodu görmekteyiz! Ama bu örnek, başka bir dilde biraz uğraştırırdı. Ne bileyim, birden fazla işlev ve birçok değişken ile başa çıkılması vakit alıcı olurdu...

Özetle, başında beri teorik yaklaştığımız chunks() olanağı bize pratikte böyle sonuçlar verebiliyor.

Sevgiler, saygılar...