Bu verileri depolamanın en etkili yolu nedir?


9

Bazı eski VB kodlarını yeniden yazmaktan sorumluyum. Nasıl çalıştığını anlıyorum, ancak yaptıklarını yapmanın çok daha verimli bir yolu olduğunu hissediyorum. Ne olduğunu anlayamıyorum. İşte veri gereksinimleri açısından yapmam gerekene gerçekten benzeyen bir örnek.

Kullanıcı bir GUI'de araba üreticisi, yapımı, modeli ve rengini seçmelidir. Ben böyle bir şey görünüyor büyük bir metin dosyası var:

Ford Truck F150 red
Ford Truck F150 blue
Ford Truck F150 black
Ford Truck F150 silver
Ford Truck F250 red
Ford Truck F250 green
Ford Sedan Taurus red
Ford Sedan Taurus green
Ford Sedan Taurus white
Ford...
...

Subaru SUV Forester blue
Subaru SUV Forester red
Subaru SUV Outback Black
Subaru SUV Outback Green
Subaru SUV Outback Blue
Subaru SUV Outback Red
Subaru...
...

etc.

İlk seçim Subaru Yani eğer, ikinci kutu (marka) olmalıdır değil Subarus hiçbiri kamyonlar çünkü Kamyon seçmek için bir seçenek vardır. Onlar Ford Sedan ve Boğa seçeneğini Benzer şekilde, ardından son kutu (renk) olmalıdır değil mavi seçmek için bir seçenek göstermektedir. Veya Siyah. Veya kırmızı, yeşil veya beyaz dışında herhangi bir şey.

Benden önce kodu yazan insanlar bununla geldi (python-y psuedocode'da):

def getValidOptions():
    items = []
    for i from 0 to numRows:
        options = getLine().split()
        if selectingManufacturer:
            if options[0] not in items:
                items.append(options[0])
        else if selectingMake:
            if selectedManufacturer == options[0] and options[1] not in items:
               items.append(options[1])
        else if selectingModel:
            if selectedManufacturer == options[0] and selectedMake == options[1] and options[2] not in items:
                items.append(options[2])
        else if selectingColor:
            if selectedManufacturer == options[0] and selectedMake == options[1] and selectedModel == options[2] and options[3] not in items:
                items.append(options[3])
    return items

Bence bu hem algoritma düzeyinde hem de sözdizimi düzeyinde iğrenç. Birincisi, doğru yapılırsa sadece birkaç satırdan okunması gerektiğinde tüm dosyayı ayrıştırır. Bunu daha da verimsiz hale getirmek için, gerçek verilerim 4 yerine 4 seçenek arasından seçim yapabiliyor.

Verileri dosyada saklamanın farklı bir yolunu ya da getValidOptionsişlevi hem daha güzel hem de daha verimli hale getirmek için ayrıştırmanın farklı bir yolunu arıyorum . Bunu yapmamın bir yolu var mı?


2
neden bir veritabanı kullanmıyorsunuz?
Tulains Córdova

Yanıtlar:


6

Okuduğum diğer tüm cevaplar, iki çok temel yazılım geliştirme kuralını göz ardı ediyor gibi görünüyor:

  • önce gereksinimleri netleştirin (özellikle performans ve depolama gereksinimleri)

  • Basit Tut, Aptal (bkz. KISS )

"Metin dosyası büyük" yazdınız, ama çok büyük yazmadı , bu yüzden aslında bağırsak duygu dışında boyutu ile yanlış bir şey olmadığını varsayalım. Bu nedenle, dosyayı yüklemek aslında çok uzun sürmezse ve BT departmanınız veya başka biri boşa harcanan disk alanından şikayet etmezse ve hiç kimse dosyayı korumakta sorun yaşamadığından şikayet etmiyorsa, dosya biçimini olduğu gibi hafife almayın - sadeliğin değeri.

Ayrıca algoritmanın verimliliğinden de şikayet ediyorsunuz, ki bu aslında olabildiğince verimli değil, ama çok büyük bir avantajı var: beyin ölümü basit ve çalışıyor. Yeterince verimli olduğu sürece erken optimizasyon uygulamayın.

Programın yeterince hızlı çalıştığını varsayalım, önce sormanız gereken şey, basitlik ve KURU ilkesi açısından kodu nasıl geliştirebileceğinizdir? Ve bu gerçekten de iyileştirilmesi gereken bir nokta, çünkü mevcut kod KURU değil. Örneğin, "daha yüksek seviyelerdeki" seçenekler geçerli hatla eşleşirse, neredeyse aynı kod bloğu testinin dört katı görünür. Bu, aynı tür "ekleme" çağrısının dört katına neden olur (gerçek kodunuzda tekrarlama gerçekleşir) yazdığınız gibi en az altı kez). Sayısal bir seçim seviyesi girerek veya önceden seçili seçenekleri sıralı bir listede geçirerek kolayca önleyebilirsiniz. Sahte kodunuzu kullanarak,

# selectedOptions is a list, containing either nothing, or "selectedManufacturer"
# or [selectedManufacturer, selectedMake], ..., and so on
def getValidOptions(selectedOptions):
    items = []
    level = selectedOptions.size()
    for i from 0 to numRows:
        options = getLine().split()
        if selectedOptions == options[0:level-1] and options[level] not in item:
            items.append(options[level])
    return items

Yani bu aslında aynı algoritma ve tekrarlanan kodlar yok.

Çok açık olduğu için getValidOptionsbirden çok kez çağrılacak vardır (en azından seviye başına bir kez), ben (bu durumda zaten değilse) sadece bir optimizasyon uygulamak için öneriyoruz: yapmak emin getLinefonksiyonu ana bellekten verileri çeker ve yapmayan dosyayı diskten tekrar tekrar okuyun.


NumRows döngüsünden önce "level = selectedOptions.size ()" öğesini taşımak istiyorsunuz.
AI Breveleri

6

Sahip olduğunuz veriler, her üretici için bir model ağacına sahip olduğunuz ve her model için bir renge sahip olduğunuz ağaç benzeri bir yapıya sahiptir.

Böylece, bu verilerin sürecini iki adımda ayırabilirsiniz:

  1. Metin dosyasında yapılan herhangi bir güncellemeden sonra, o dosya dosyasını işleyip ağaç yapısına dönüştürmeniz gerekir.
  2. Uygulamayı yüklerken, yalnızca ağaç yapısını yüklersiniz.

Ağaç yapısı, karma , ilişkilendirilebilir dizi veya Java, PHP, Javascript veya Python gibi dillerde sözlük olarak adlandırılan uygulama ile uygulanabilir . Bu yapı ile:

  • İlk anahtarlar üreticilerdir.
  • Değerleri, her bir anahtarın model olduğu başka bir karma veya sözlüktür .
  • Değerleri renklerdir. Veya anahtarlarında üçüncü seviyeyi ve değer olarak dördüncü seviyeyi tutan başka bir yapı.
  • Ve bunun gibi...

Programlama dilinize bağlı olarak, bu daha hızlı veya daha yavaş uygulanabilir. Örneğin:

  • C # : Bir ağaç yapısı 1 uygulamak ve sonra serileştirilebilir olarak işaretleyebilirsiniz.
  • VB.Net : ağaç yapısını tek bir uygulamada oluşturabilir ve bir dosyada serileştirebilirsiniz.
    • Bunun için böyle bir şey Runtime.Serialization.Formatters.Binary.BinaryFormatteryararlı olabilir, ancak VB.Net ile serileştirme konusunda uzman değilim.
  • Javascript : Uygulama her yüklendiğinde yüklenmesi gereken bir JSON dosyasında ağaç yapısı oluşturabilirsiniz.
  • PHP : ağaç veri yapısının serileştirilmiş bir sürümünü oluşturabilir veya bir JSON yükleyebilirsiniz.
  • Java : Bu veri yapısını serileştirerek Classarabirimi uygulayan bir veri oluşturabilirsiniz java.io.Serializable.

Kaynaklar :

1: https://dvanderboom.wordpress.com/2008/03/15/treet-implementing-a-non-binary-tree-in-c/
- C # 'da bir ağaç uygulaması hakkında tam bir açıklama.
- Birisinin o nesneyi serileştirmeyi sorduğu bir yorum ve bu yorumun cevabını arayın .


1
Evet, bir ağaç kullanmayı düşünmüştüm, ama en iyi fikir olup olmadığını bilmiyorum çünkü C # 'da yerleşik bir ağaç yapısı (bildiğim) yok ve proje oldukça küçük, bu yüzden eğer bir tree with an arbitrary number of nodesuygulama üzerinde çok fazla zaman harcamak buna değer .
James

Henüz C # konusunda uzman değilim, ama en azından Java ve PHP gibi diğer dillerde, her anahtarın başka bir sözlüğe değer verebileceği bir sözlükler olabilir.
Nicolás

Cevabımı güncelledim. Karma veya sözlük alternatifi hakkında ne düşündüğünüzü görün. Ayrıca ilginç bir makaleyle bir referans ekledim.
Nicolás

3

Verileri depolamanın basit bir yolu, verileri bir SQLite veritabanına doldurmaktır. SQLite, çoğu SQL veritabanından farklı olarak, bir uygulama dosyası formatı olarak kullanım için çok uygundur. Bu yaklaşımın çeşitli faydaları vardır:

  1. Bir serileştiriciyi veya bir serileştiriciyi kodlamaya gerek yoktur.
  2. Dosya çok sayıda mevcut program tarafından düzenlenebilir ve sorgulanabilir.
  3. Soruda bahsettiğiniz koşullu dağınıklıktan kaçınılır. Açılır menüleri sınırlamak için, her sütuna (ör select distinct model where manufacturer='ford' and color = 'red'.) Karşılık gelen basit bir konum cümlesi oluşturun .

Bu sizi SQL öğrenmeye zorlar, ancak özel bir dosya biçimi öğrenme ihtiyacını ortadan kaldırır.


1

Dosyadaki satırlara rasgele erişebildiğinizi ve böylece dosyayı bir kayıt dizisi olarak ele alabileceğinizi varsayıyorum. Çizgilere rastgele erişemiyorsanız, sahip olduğunuz algoritma yapabileceğiniz en iyisidir.

En hızlı erişim için, verileri 6 dosyada saklayın; burada her dosya bir sonrakine bir indekstir.

Düz dosya dizinleri oluşturmanın birkaç yolu vardır. Genellikle bir alt simge aralığı kullanırım. Kullanıcı her seçimi yaparken, bir sonraki dosyanın okumasını sınırlamak için aralığı kullanın.

Sağladığınız örnek veriler için endeksleri nasıl oluşturacağım aşağıda açıklanmıştır.

Tabii ki dosya sıralanmalıdır. İllüstrasyon için numaralandırdım; satır numaraları dosyada görünmemelidir.

--| file3.dat |--
 0 Ford Truck F150 red
 1 Ford Truck F150 blue
 2 Ford Truck F150 black
 3 Ford Truck F150 silver
 4 Ford Truck F250 red
 5 Ford Truck F250 green
 6 Ford Sedan Taurus red
 7 Ford Sedan Taurus green
 8 Ford Sedan Taurus white
 9 Subaru SUV Forester blue
10 Subaru SUV Forester red
11 Subaru SUV Outback Black
12 Subaru SUV Outback Green
13 Subaru SUV Outback Blue
14 Subaru SUV Outback Red

İlk dizini oluşturmak için, dosyadaki ilk üç alanın her benzersiz birleşimi için bir kayıt oluşturun. Her kayıtta, bu kombinasyonun göründüğü ilk ve son satır numaralarını saklayın.

--| file2.dat |--
 0 Ford Truck F150       0   3
 1 Ford Truck F250       4   5
 2 Ford Sedan Taurus     6   8
 3 Subaru SUV Forester   9  10
 4 Subaru SUV Outback   11  14

İkinci endeks, birinci endeksin ilk iki alanı kullanılarak benzer şekilde oluşturulur.

--| file1.dat |--
 0 Ford Truck        0   1
 1 Ford Sedan        2   2
 2 Subaru SUV        3   4

Ve üçüncü, bu durumda en üst düzey, dizin.

--| file0.dat |--
 0 Ford          0   1
 1 Subaru        2   2

Ben kavramı açıklamak düşünüyorum, ama genel olarak son alanı bırakarak ve yinelenen kayıtları ortadan kaldırarak bir dizin oluşturmak.

Gereksiz verileri ortadan kaldırarak dosya depolama gereksinimini daha da azaltabilirsiniz.

Örneğin, her bir dizin kaydındaki "ilk" alt simge her zaman önceki kaydın "son" alt abonesinden bir veya önceki kayıt yoksa sıfırdır. Bu yüzden "ilk" abonelikleri saklamanız gerekmez. Bunları örnekleme için aşağıdaki yerde bırakıyorum.

Ayrıca, seçim listesini doldurmak için her kayıttaki yalnızca son alanı kullanacağınızdan, diğer alanları depolamanız gerekmez.

Dizin kaskadının minimum yorumlaması şöyle görünür, burada kene 'dosyada gerçekte saklanmayan bir sayıyı gösterir.

--| file0.dat |--
 0' Ford         0'   1
 1' Subaru       2'   2

--| file1.dat |--
 0' Truck        0'   1
 1' Sedan        2'   2
 2' SUV          3'   4

--| file2.dat |--
 0' F150         0'   3
 1' F250         4'   5
 2' Taurus       6'   8
 3' Forester     9'  10
 4' Outback     11'  14

--| file3.dat |--
 0' red
 1' blue
 2' black
 3' silver
 4' red
 5' green
 6' red
 7' green
 8' white
 9' blue
10' red
11' Black
12' Green
13' Blue
14' Red

Bir dizinden seçim listesini doldurduğunuzda, okunan satırları sınırlamak için kullanıcının önceki dizindeki seçiminden "ilk" ve "son" abonelikleri kullanırsınız.

Misal:

İlk seçim listesini hepsinden doldurursunuz file0.dat. (Ford, Subaru)

Kullanıcı "Ford" u seçer. Karşılık gelen abonelikler 0 ve 1'dir.

İkinci seçim listesini 0 - 1 arasındaki satırlardan doldurursunuz file1.dat. (Kamyon, Sedan)

Kullanıcı "Sedan" ı seçer. Karşılık gelen abonelikler 2 ve 2'dir.

Gördüğünüz gibi, kullanıcı seçtiği zaman, örneğin "Ford" "Sedan" "Boğa" file3.datdördüncü seçim listesini doldurmak için sadece 6 ile 8 arasındaki satırları okumanız gerektiğini göreceksiniz .

Oldukça uzun bir açıklama için özür dilerim ama burada çok geç ve kısa bir yazı yazmak için zamanım yok.

EKLENDİ: Daha fazla düşünüldüğünde, dosyalar tek bir dosyada birleştirilebilir.

--| file.dat |--
 0' -            1'   2
 1' Ford         3'   4
 2' Subaru       5'   5
 3' Truck        6'   7
 4' Sedan        8'   8
 5' SUV          9'  10
 6' F150        11'  14
 7' F250        15'  16
 8' Taurus      17'  19
 9' Forester    20'  21
10' Outback     22'  25
11' red          -'   -
12' blue         -'   -
13' black        -'   -
14' silver       -'   -
15' red          -'   -
16' green        -'   -
17' red          -'   -
18' green        -'   -
19' white        -'   -
20' blue         -'   -
21' red          -'   -
22' Black        -'   -
23' Green        -'   -
24' Blue         -'   -
25' Red          -'   -

Bu, birden çok dosya sürümü gibi kullanılır, ancak ilk abonelik aralığını içermek için kukla ilk satıra ihtiyacınız vardır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.