Apa cara paling efisien untuk menyimpan data ini?

9

Saya bertugas menulis ulang beberapa kode VB lama. Saya mengerti cara kerjanya, tetapi saya merasa ada cara yang jauh lebih efisien untuk melakukan apa yang mereka lakukan. Aku hanya tidak tahu apa itu. Berikut adalah contoh yang dibuat bahwa dalam hal persyaratan data benar-benar mirip dengan apa yang perlu saya lakukan.

Pengguna harus memilih pabrikan, membuat, model dan warna mobil mereka dalam GUI. Saya memiliki file teks besar yang terlihat seperti ini:

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.

Jadi jika pilihan pertama adalah Subaru, kotak kedua (make) seharusnya tidak memiliki pilihan untuk memilih Truk karena tidak ada Subarus adalah truk. Demikian pula, jika mereka memilih Ford, Sedan dan Taurus, maka kotak terakhir (warna) tidak akan menunjukkan opsi untuk memilih biru. Atau Hitam. Atau apapun selain merah, hijau atau putih.

Orang-orang yang menulis kode sebelum saya membuat ini (dalam python-y psuedocode):

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

Saya pikir itu hanya mengerikan, baik pada level algoritma, dan pada level sintaksis. Untuk satu, itu mem-parsing seluruh file, ketika itu hanya perlu membaca beberapa baris jika dilakukan dengan benar. Untuk membuat ini lebih tidak efisien, data asli saya memiliki 6 opsi untuk dipilih, bukan hanya 4. Ini juga menyimpan lebih banyak data maka perlu, mengingat jumlah duplikasi data.

Saya mencari cara berbeda untuk menyimpan data dalam file, atau cara parsing yang berbeda untuk membuat getValidOptionsfungsi keduanya lebih cantik dan lebih efisien. Apakah ada cara saya bisa melakukan ini?

James
sumber
2
mengapa tidak menggunakan database?
Tulains Córdova

Jawaban:

6

Semua jawaban lain yang saya baca tampaknya mengabaikan dua aturan dasar pengembangan perangkat lunak:

  • mengklarifikasi persyaratan terlebih dahulu (terutama persyaratan kinerja dan penyimpanan)

  • Keep It Simple, Stupid (lihat KISS )

Anda menulis "file teks besar", tetapi tidak menulis terlalu besar, jadi saya berasumsi sebenarnya tidak ada yang salah dengan ukurannya kecuali firasat Anda. Jadi, jika memuat file sebenarnya tidak terlalu lama, dan departemen TI Anda atau orang lain tidak mengeluh tentang ruang disk yang terbuang, dan tidak ada yang mengeluh memiliki masalah dalam mempertahankan file, biarkan format file apa adanya - jangan meremehkan nilai kesederhanaan.

Anda juga mengeluh tentang efisiensi algoritme, yang sebenarnya tidak seefisien mungkin, tetapi ia memiliki satu keuntungan yang sangat besar: sederhana dan bekerja dengan sangat sederhana. Jadi selama itu cukup efisien, jangan menerapkan optimasi prematur.

Jadi mari kita asumsikan program bekerja cukup cepat, apa yang harus Anda tanyakan pertama adalah bagaimana Anda dapat meningkatkan kode dalam hal kesederhanaan dan prinsip KERING? Dan itu memang titik yang harus ditingkatkan, karena kode saat ini tidak KERING. Dalam contoh Anda, muncul empat kali pengujian blok kode yang hampir sama jika opsi pada "tingkat yang lebih tinggi" cocok dengan baris saat ini, yang menghasilkan empat kali panggilan "tambahkan" yang sama (dalam kode Anda yang sebenarnya, pengulangan terjadi setidaknya enam kali, seperti yang Anda tulis). Anda dapat dengan mudah menghindari itu dengan memperkenalkan tingkat pemilihan numerik, atau melewati opsi yang sudah dipilih dalam daftar yang dipesan. Menggunakan pseudo-code Anda, ini mengarah ke sesuatu di sepanjang baris

# 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

Jadi ini pada dasarnya adalah algoritma yang sama tanpa kode yang diulang lagi.

Karena jelas getValidOptionsharus dipanggil lebih dari sekali (setidaknya sekali per level), saya sarankan untuk menerapkan hanya satu optimasi (jika ini belum terjadi): pastikan getLinefungsi menarik datanya dari memori utama, dan tidak baca file dari disk lagi dan lagi.

Doc Brown
sumber
Anda ingin memindahkan "level = selectedOptions.size ()" sebelum loop numRows.
AI Breveleri
6

Nah, data yang Anda miliki memiliki struktur seperti pohon, di mana untuk setiap produsen Anda memiliki pohon model, dan untuk setiap model Anda memiliki warna (dan sebagainya).

Jadi, Anda dapat memisahkan proses data ini dengan dua langkah:

  1. Setelah pembaruan ke file teks, Anda harus memproses file file itu dan mengubahnya menjadi struktur pohon.
  2. Saat memuat aplikasi, Anda hanya memuat struktur pohon.

Struktur pohon dapat diimplementasikan dengan apa yang disebut hash , array asosiatif atau kamus dalam bahasa seperti Java, PHP, Javascript atau Python. Dengan struktur ini, Anda memiliki:

  • Kunci pertama adalah pabrikan.
  • Nilai-nilai mereka hanyalah hash atau kamus lain di mana setiap kunci adalah modelnya.
  • Nilai-nilai mereka adalah warna. Atau struktur lain yang menyimpan kunci mereka di tingkat ketiga dan sebagai nilai tingkat keempat.
  • Dan seterusnya...

Tergantung pada bahasa pemrograman Anda, ini dapat diimplementasikan lebih cepat atau lebih lambat. Sebagai contoh:

  • C # : Anda bisa mengimplementasikan struktur Tree 1 , dan kemudian menandainya sebagai serializable.
  • VB.Net : Anda dapat membuat struktur pohon dalam satu aplikasi, dan membuat serialisasi dalam file.
    • Untuk ini, sesuatu seperti Runtime.Serialization.Formatters.Binary.BinaryFormatterbisa bermanfaat, tapi saya bukan ahli dalam membuat cerita bersambung dengan VB.Net.
  • Javascript : Anda dapat membuat struktur pohon dalam file JSON, yang harus dimuat setiap kali aplikasi dimuat.
  • PHP : Anda bisa membuat versi berstruktur struktur data pohon, atau Anda bisa memuat JSON juga.
  • Java : Anda bisa membuat serial struktur data itu, membuat Classyang mengimplementasikan antarmuka java.io.Serializable.

Referensi :

1: https://dvanderboom.wordpress.com/2008/03/15/treet-implementing-a-non-binary-tree-in-c/
- Penjelasan lengkap tentang penerapan pohon di C #.
- Cari komentar di mana seseorang bertanya tentang cerita bersambung objek itu, dan jawaban untuk komentar itu.

Nicolás
sumber
1
Ya, saya sudah berpikir tentang menggunakan pohon, tapi saya tidak tahu apakah itu ide terbaik karena tidak ada struktur pohon dibangun (yang saya tahu) di C #, dan proyek ini cukup kecil sehingga saya tidak tahu apakah akan sangat berharga untuk menghabiskan banyak waktu mengerjakan tree with an arbitrary number of nodesimplementasi.
James
Sampai sekarang saya bukan ahli dengan C #, tetapi setidaknya dalam bahasa lain seperti Java dan PHP Anda dapat memiliki semacam kamus, di mana setiap kunci dapat memiliki nilai kamus lain.
Nicolás
Saya memperbarui jawaban saya. Lihat pendapat Anda tentang hash atau alternatif kamus. Saya juga menambahkan referensi dengan artikel yang menarik.
Nicolás
3

Salah satu cara sederhana untuk menyimpan data adalah dengan memasukkannya ke dalam database SQLite. SQLite, tidak seperti kebanyakan database SQL, sangat cocok untuk digunakan sebagai format file aplikasi. Pendekatan ini memiliki beberapa manfaat:

  1. Tidak perlu kode serializer atau deserializer.
  2. File dapat diedit dan dapat diminta oleh berbagai program yang ada.
  3. Kekacauan bersyarat yang Anda sebutkan dalam pertanyaan dihindari. Untuk membatasi dropdown, buat klausa sederhana di mana terhadap setiap kolom (mis., select distinct model where manufacturer='ford' and color = 'red').

Ini memaksa Anda untuk belajar SQL, tetapi menghindari kebutuhan untuk mempelajari format file khusus.

Brian
sumber
1

Saya berasumsi Anda dapat mengakses baris secara acak dalam file, dan dengan demikian dapat memperlakukan file sebagai array catatan. Jika Anda tidak dapat mengakses jalur secara acak, maka algoritma yang Anda miliki adalah yang terbaik yang dapat Anda lakukan.

Untuk akses tercepat, simpan data dalam 6 file, di mana setiap file diindeks ke file berikutnya.

Ada banyak cara untuk membuat indeks flatfile. Saya biasanya menggunakan rentang subskrip. Saat pengguna membuat setiap pilihan, gunakan rentang untuk membatasi pembacaan file selanjutnya.

Inilah cara saya membuat indeks untuk data sampel yang Anda berikan.

Tentu saja file tersebut harus disortir. Saya sudah menghitung garis untuk ilustrasi; nomor baris tidak boleh muncul dalam file.

--| 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

Untuk membuat indeks pertama, buat catatan untuk setiap kombinasi unik dari tiga bidang pertama dalam file. Di setiap catatan, simpan nomor baris pertama dan terakhir tempat kombinasi itu muncul.

--| 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

Indeks kedua dibangun dengan cara yang sama, menggunakan dua bidang pertama dari indeks pertama.

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

Dan yang ketiga, level teratas dalam hal ini, indeks.

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

Saya pikir saya terlalu menjelaskan konsep, tetapi secara umum Anda membuat indeks dengan menjatuhkan bidang terakhir dan menghilangkan duplikat catatan.

Anda selanjutnya dapat mengurangi persyaratan penyimpanan file dengan menghilangkan beberapa data yang berlebihan.

Misalnya, subskrip "pertama" dalam setiap catatan indeks selalu lebih dari subskrip "terakhir" dari catatan sebelumnya, atau nol jika tidak ada catatan sebelumnya. Jadi, Anda tidak perlu menyimpan subskrip "pertama". Saya meninggalkan mereka di tempat di bawah untuk ilustrasi.

Juga, karena Anda hanya akan menggunakan bidang terakhir di setiap catatan untuk mengisi daftar pilihan, Anda tidak perlu menyimpan bidang lainnya.

Penyajian minimum kaskade indeks berakhir tampak seperti ini, di mana tanda centang 'menunjukkan angka yang sebenarnya tidak disimpan dalam file.

--| 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

Saat Anda mengisi daftar pilihan dari indeks, Anda menggunakan subskrip "pertama" dan "terakhir" dari pilihan pengguna dalam indeks sebelumnya untuk membatasi baris yang dibaca.

Contoh:

Anda mengisi daftar pilihan pertama dari semua file0.dat. (Ford, Subaru)

Pengguna memilih "Ford". Subskrip yang sesuai adalah 0 dan 1.

Anda mengisi daftar pilihan kedua dari baris 0 hingga 1 dari file1.dat. (Truk, Sedan)

Pengguna memilih "Sedan". Subskrip yang sesuai adalah 2 dan 2.

Seperti yang Anda lihat, pada saat pengguna telah memilih, misalnya, "Ford" "Sedan" "Taurus" Anda akan menemukan bahwa Anda hanya perlu membaca baris 6 sampai 8 file3.datuntuk mengisi daftar pilihan keempat.

Saya minta maaf untuk deskripsi yang agak panjang tapi ini sudah sangat terlambat dan saya tidak punya waktu untuk menulis yang singkat.

TAMBAH: Dipikirkan lebih lanjut, file dapat digabung menjadi satu.

--| 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          -'   -

Ini digunakan persis seperti versi banyak file, kecuali Anda memerlukan baris dummy pertama untuk berisi rentang subskrip pertama.

AI Breveleri
sumber