Forum: Ders Arası RSS
String[] den değer silmek
Avatar
huseyin #1
Üye Haz 2012 tarihinden beri · 363 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: String[] den değer silmek
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
Huseyin
acehreli (Moderatör) #2
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ı
Aynı soru geçen gün D.learn haber grubunda soruldu:

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

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
Avatar
Salih Dinçer #3
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #1
Ş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.
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Bu mesaj Salih Dinçer tarafından değiştirildi; zaman: 2013-02-05, 13:29.
Değişiklik nedeni: Dip not eklendi...
Avatar
huseyin #4
Üye Haz 2012 tarihinden beri · 363 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #2
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 :( ?
Huseyin
Avatar
huseyin #5
Üye Haz 2012 tarihinden beri · 363 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #3
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
Huseyin
acehreli (Moderatör) #6
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ı
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
Avatar
Salih Dinçer #7
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
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
5. test       64,4          54,7


(Ölçü birimi sn. cinsindendir ve debug(on) ile dizi sonucunu ekrana yansıtma, derleme anında iptal edilmiştir.)
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Avatar
Salih Dinçer #8
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Üçü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
4. test       55,9          46,1          44,3
5. 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ı.
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
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:
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-19, 07:55:49 (UTC -08:00)