Thread overview
String[] den değer silmek
Feb 05, 2013
huseyin
Feb 05, 2013
Salih Dinçer
Feb 05, 2013
huseyin
Feb 05, 2013
Salih Dinçer
Feb 05, 2013
Salih Dinçer
Feb 05, 2013
huseyin
February 05, 2013

Merhaba Arkadaşlar

string[] dizim=["1","2","3"];
dizim[2]=string.init;

Yukarıdaki şekilde yaptığımda dizim
["1","","3"] şeklinde gözüküyor remove gibi bir işlev var mı dlang a baktım ama bulamadım
Teşekkürler

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 05, 2013

Şu kod işini görecektir:

 T[] diziKes(T)(T[] dizi, size_t k)
 in { assert(k < dizi.length); }
 body { T[] result;
 if (k) result = dizi[0..k];
 return result ~ dizi[k+1..$];
 } // diziKes(dizim, 1).writeln;

Dip Not: Ben kodu deniyorken Ali hocam cevap yazmış, tekrar gibi oldu.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 05, 2013

Teşekkür Ederim gerçekten gece bu saatte cevap gelmez diyordum :)ama yanılmışım
@acehreli sizce hangisi daha performanslı dizim biraz uzun da :( ?

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 05, 2013

Alıntı (Salih Dinçer):

>

Şu kod işini görecektir:

>   T[] diziKes(T)(T[] dizi, size_t k)
>   in { assert(k < dizi.length); }
>   body { T[] result;
>   if (k) result = dizi[0..k];
>   return result ~ dizi[k+1..$];
>   } // diziKes(dizim, 1).writeln;
> ```

> **Dip Not:** Ben kodu deniyorken Ali hocam cevap yazmış, tekrar gibi oldu.
>
Teşekkür ederim önemli değil ancak performans açısından en iyisi hangisi onu düşünüyorumda

-- 
[ Bu gönderi, <http://ddili.org/forum>'dan dönüştürülmüştür. ]
February 05, 2013

Az önce testi, tek çekirdekli netbook ile 5 tekrar olacak şekilde yaptım. Çarpıcı şekilde sonuçlar her seferinde farklı çıktı. Hatta birinde (4. test) tam tersi sonuç elde ettim. Elbette arka planda IIS dahil bir çok uygulama çalışıyordu. Bunların etkisi olabilir...

Sonuçlar şöyle:
' Yöntem 1 Yöntem 2

  1. test 58,2 54,9
  2. test 57,9 49,6
  3. test 63,6 52,9
    '4. test 47,3 53,8'
  4. test 64,4 54,7'

(Ölçü birimi sn. cinsindendir ve debug(on) ile dizi sonucunu ekrana yansıtma, derleme anında iptal edilmiştir.)

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 05, 2013

Üçüncü bir yöntem denedim ve daha iyi/istikrarlı bir sonuç elde ettim. Bu hepinizin tahmin edeceği gibi en basiti. Referans edilen dilim üzerinden yapılan bir döngüden oluşuyor. Tek yaptığı, kesilmek istenen elamanın üzerine sırasıyla bir sonrakini eşitlemek...

Sonuçlar şöyle:
' Yöntem 1 Yöntem 2 Yöntem 3

  1. test 63,3 52,6 51,5
  2. test 58,8 47,3 47,4
    '3. test 46,6 52,3 50,7'
  3. test 55,9 46,1 44,3
  4. test 58,3 47,2 47,3'

Yine saniye cinsinden olan bu sonuçlara bakılınca; 3. yöntem, 2. yöntem ile uyumlu gidiyor. Buradan aralık algoritması benzer temel yöntemi seçmiş olduğunu çıkarabiliriz. Dilim kullandığımızda ise bazen daha iyi sonuç elde ettiğini görüyoruz. Herhalde daha akıllı bir algoritma olduğu için, o an ki bellek durumuna göre pratik bir sonuç elde ediyor olmalı.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 05, 2013

Aynı soru geçen gün D.learn haber grubunda soruldu:

http://forum.dlang.org/thread/mvztrmbrlyjlfjhypitz@forum.dlang.org

Tam bu işi yapan işlev yok ama orada üç yöntem gösterdim:

import std.stdio;

void removeAt(T : U[], U)(ref T dilim, size_t indeks) in {
   assert(indeks <= dilim.length);

} body {
   dilim = dilim[0..indeks] ~ dilim[indeks + 1 .. $];
}

void main()
{
   string[] dizim=["1","2","3"];
   dizim.removeAt(1);

   assert(dizim == ["1", "3"]);
}

Yukarıdakinin bir sorunu var: dizim'in türü string olduğunda böyle bir işlem ancak ASCII metinlerle kullanılabilir. (string, UTF-8 kod birimlerinden oluştuğu için.) Bir de sakıncası var: removeAt hevesli bir işlev olduğu için dizi uzun olduğunda yavaş kalacaktır.

İkinci yöntem Unicode dizgileriyle de çalışır ama heveslilik [sakıncası onda da var. İşin güzeli, bu her türlü RandomAccessRange aralığıyla çalışır:

import std.stdio;
import std.range;

R removeAt(R)(R aralık, size_t indeks)
{
   auto gerisi = aralık.save;
   gerisi.popFrontN(indeks + 1);
   return aralık[0 .. indeks] ~ gerisi;
}

void main()
{
   string[] dizim=["1","2","3"];
   dizim = dizim.removeAt(1);

   assert(dizim == ["1", "3"]);
}

Üçüncü yöntem ise tembel olarak işliyor ve sonucu yine bir aralık olarak döndürüyor. Böylece sonuç tekrardan belki de çok uzun bir dizi olarak döndürülmemiş oluyor:

import std.stdio;
import std.range;
import std.algorithm;

auto removeAt(R)(R aralık, size_t indeks)
{
   auto gerisi = aralık.save;
   gerisi.popFrontN(indeks + 1);
   return [aralık[0 .. indeks], gerisi].chain.joiner;
}

void main()
{
   string[] dizim=["1","2","3"];
   auto sonuç = dizim.removeAt(1);

   assert(sonuç.array == ["1", "3"]);
}

'sonuç' tembel bir aralık olduğundan o aralıktan bir dizi oluşturmak gerektiğinde .array çağrılır. (Ama çoğu durumda gerekmez; yukarıda assert içinde kullanabilmek için çağırdım.)

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

February 05, 2013

Altın kural: Denemeden bilemeyiz. :)

Dizi uzunsa tembel yöntemler genelde daha iyidir. Ama bu, sen o sonucu bir aralık (range) olarak kullanmaya devam edeceksen böyledir. Yoksa, .array yaptığın an, yani aralıktaki bütün elemanlardan oluşan bir dizi yaptığın an, o tembel aralığın yararı kalmamış olur. O zaman performans kazancı kalmıyor. Tabii yapılması gerekiyorsa yapılır... Duruma göre değişir.

Bir örnek: Çok uzun bir dizinin ikinci elemanını sildikten sonra yalnızca ilk 10 elemanını kullanalım:

import std.stdio;
import std.conv;
import std.datetime;
import std.range;
import std.algorithm;

enum uzunluk = 1_000_000;

string[] uzunDizi()
{
   string[] sonuç;
   foreach (i; 0 .. uzunluk) {
       sonuç ~= i.to!string;
   }

   return sonuç;
}

void removeAt_yöntem1(T : U[], U)(ref T dilim, size_t indeks)
{
   dilim = dilim[0..indeks] ~ dilim[indeks + 1 .. $];
}

void yöntem1()
{
   auto dizi = uzunDizi();
   dizi.removeAt_yöntem1(1);

   writeln(dizi[0 .. 10]);
}

auto removeAt_yöntem2(R)(R aralık, size_t indeks)
{
   auto gerisi = aralık.save;
   gerisi.popFrontN(indeks + 1);
   return [aralık[0 .. indeks], gerisi].chain.joiner;
}

void yöntem2()
{
   auto dizi = uzunDizi();

   // dizi'de değişiklik yok. Sonucu kullanıyoruz:
   auto sonuç = dizi.removeAt_yöntem2(1);
   writeln(sonuç.take(10));
}

void main()
{
   auto ölçümler = benchmark!(yöntem1, yöntem2)(10);

   writefln("yöntem1: %8s ms", ölçümler[0].to!("msecs", int));
   writefln("yöntem2: %8s ms", ölçümler[1].to!("msecs", int));
}

Çıktısı:
'yöntem1: 7885 ms
yöntem2: 6812 ms'

Dizi uzunluğunu 10 milyona çıkartınca fark daha da artıyor (bu sefer benchmark'a parametre olarak 1 verdim yoksa çok yavaş oluyordu):
'yöntem1: 14097 ms
yöntem2: 7834 ms
'

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]