Cách hiệu quả nhất để lưu trữ dữ liệu này là gì?


9

Tôi phụ trách viết lại một số mã VB cũ. Tôi hiểu cách thức hoạt động của nó, nhưng tôi cảm thấy như có một cách hiệu quả hơn nhiều để làm những gì họ đã làm. Tôi chỉ không thể hiểu nó là gì. Dưới đây là một ví dụ giả định rằng về mặt yêu cầu dữ liệu thực sự giống với những gì tôi cần làm.

Người dùng phải chọn ra nhà sản xuất, chế tạo, kiểu dáng và màu sắc của chiếc xe của họ trong GUI. Tôi có một tệp văn bản lớn trông giống như thế này:

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.

Vì vậy, nếu lựa chọn đầu tiên là Subaru, hộp thứ hai (make) không nên có tùy chọn để chọn Xe tải vì không có Subarus nào là xe tải. Tương tự, nếu họ chọn Ford, Sedan và Taurus, thì hộp cuối cùng (màu) sẽ không hiển thị tùy chọn để chọn màu xanh. Hoặc Đen. Hoặc bất cứ thứ gì khác ngoài màu đỏ, xanh lá cây hoặc trắng.

Những người đã viết mã trước khi tôi nghĩ ra điều này (trong pyued-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

Tôi nghĩ rằng đó chỉ là gớm ghiếc, cả ở cấp độ thuật toán và cấp độ cú pháp. Đối với một, nó phân tích cú pháp thông qua toàn bộ tập tin, khi nó chỉ cần đọc qua một vài dòng nếu được thực hiện đúng. Để làm cho điều này thậm chí không hiệu quả hơn, dữ liệu thực của tôi có 6 tùy chọn để chọn, thay vì chỉ 4. Đây cũng là lưu trữ nhiều dữ liệu hơn, sau đó cần phải có số lượng sao chép dữ liệu.

Tôi đang tìm kiếm một cách khác nhau để lưu trữ dữ liệu trong tệp hoặc một cách phân tích dữ liệu khác để làm cho getValidOptionschức năng vừa đẹp hơn vừa hiệu quả hơn. Có cách nào tôi có thể làm điều này?


2
Tại sao không sử dụng cơ sở dữ liệu?
Tulains Córdova

Câu trả lời:


6

Tất cả các câu trả lời khác tôi đọc dường như bỏ qua hai quy tắc phát triển phần mềm rất cơ bản:

  • làm rõ các yêu cầu đầu tiên (đặc biệt là các yêu cầu về hiệu năng và lưu trữ)

  • Giữ nó đơn giản, ngu ngốc (xem KISS )

Bạn đã viết "tệp văn bản lớn", nhưng không viết quá lớn, vì vậy tôi cho rằng thực sự không có gì sai với kích thước của nó ngoại trừ cảm giác ruột của bạn. Vì vậy, nếu việc tải tệp thực sự không mất quá nhiều thời gian và bộ phận CNTT của bạn hoặc người khác không phàn nàn về dung lượng đĩa bị lãng phí và không ai phàn nàn về việc gặp sự cố khi duy trì tệp, hãy để định dạng tệp như vậy - đừng đánh giá thấp giá trị của sự đơn giản.

Bạn cũng đang phàn nàn về hiệu quả của thuật toán, điều này thực sự không hiệu quả như nó có thể, nhưng nó có một lợi thế rất lớn: nó đơn giản và hiệu quả. Vì vậy, miễn là nó đủ hiệu quả, không áp dụng bất kỳ tối ưu hóa sớm nào.

Vì vậy, giả sử chương trình hoạt động đủ nhanh, điều bạn nên hỏi đầu tiên là làm thế nào bạn có thể cải thiện mã theo cách đơn giản và nguyên tắc DRY? Và đó thực sự là một điểm cần được cải thiện, vì mã hiện tại không phải là DRY. Trong ví dụ của bạn, xuất hiện bốn lần kiểm tra khối mã gần như giống nhau nếu các tùy chọn ở "mức cao hơn" khớp với dòng hiện tại, dẫn đến bốn lần cuộc gọi "nối" giống nhau (trong mã thực của bạn, xảy ra sự lặp lại ít nhất sáu lần, như bạn đã viết). Bạn có thể dễ dàng tránh điều đó bằng cách giới thiệu cấp độ lựa chọn số hoặc chuyển các tùy chọn đã chọn trong danh sách được sắp xếp. Sử dụng mã giả của bạn, điều này dẫn đến một cái gì đó dọc theo dòng

# 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

Vì vậy, đây về cơ bản là cùng một thuật toán không có mã lặp lại nữa.

Vì rõ ràng getValidOptionsphải gọi nhiều lần (ít nhất một lần cho mỗi cấp), tôi khuyên bạn chỉ nên áp dụng một tối ưu hóa (nếu điều này chưa xảy ra): đảm bảo getLinechức năng lấy dữ liệu của nó từ bộ nhớ chính, và không đọc tập tin từ đĩa nhiều lần.


Bạn muốn di chuyển "level = chọnOptions.size ()" trước vòng lặp numRows.
AI Breveleri

6

Chà, dữ liệu bạn có có cấu trúc giống như cây, trong đó với mỗi nhà sản xuất bạn có một cây mô hình và với mỗi mô hình bạn có một màu (vân vân).

Vì vậy, bạn có thể tách quy trình của dữ liệu này theo cách hai bước:

  1. Sau khi cập nhật tệp văn bản, bạn phải xử lý tệp tệp đó và chuyển đổi nó thành cấu trúc cây.
  2. Khi tải ứng dụng, bạn chỉ tải cấu trúc cây.

Cấu trúc cây có thể được thực hiện với cái được gọi là hàm băm , mảng kết hợp hoặc từ điển trong các ngôn ngữ như Java, PHP, Javascript hoặc Python. Với cấu trúc này, bạn có:

  • Chìa khóa đầu tiên là các nhà sản xuất.
  • Giá trị của chúng chỉ là một giá trị băm hoặc từ điển khác trong đó mỗi khóa là mô hình.
  • Giá trị của chúng là màu sắc. Hoặc một cấu trúc khác giữ trong khóa của họ cấp thứ ba và giá trị của cấp thứ tư.
  • Và như thế...

Tùy thuộc vào ngôn ngữ lập trình của bạn, điều này có thể được thực hiện nhanh hơn hoặc chậm hơn. Ví dụ:

  • C # : Bạn có thể triển khai cấu trúc Tree 1 , sau đó đánh dấu nó là tuần tự hóa.
  • VB.Net : bạn có thể tạo cấu trúc cây trong một ứng dụng và tuần tự hóa nó trong một tệp.
    • Đối với điều này, một cái gì đó giống như Runtime.Serialization.Formatters.Binary.BinaryFormattercó thể hữu ích, nhưng tôi không phải là chuyên gia về tuần tự hóa với VB.Net.
  • Javascript : bạn có thể tạo cấu trúc cây trong tệp JSON, phải được tải mỗi khi ứng dụng được tải.
  • PHP : bạn có thể tạo một phiên bản tuần tự của cấu trúc dữ liệu cây hoặc bạn cũng có thể tải JSON.
  • Java : bạn có thể tuần tự hóa cấu trúc dữ liệu đó, tạo ra một Classgiao diện thực hiện giao diện java.io.Serializable.

Tài liệu tham khảo :

1: https://dvanderboom.wordpress.com/2008/03/15/treet-im Hiệning
-a-non-binary-tree-in-c / - Một lời giải thích đầy đủ về việc thực hiện một cây trong C #.
- Tìm kiếm một bình luận trong đó có người hỏi về việc tuần tự hóa đối tượng đó và câu trả lời cho nhận xét đó.


1
Vâng, tôi đã nghĩ về việc sử dụng cây, nhưng tôi không biết liệu đó có phải là ý tưởng tốt nhất bởi vì không có cấu trúc cây được xây dựng (mà tôi biết) trong C #, và dự án khá nhỏ nên tôi không biết nếu nó sẽ là giá trị nó dành rất nhiều thời gian để tree with an arbitrary number of nodesthực hiện.
James

Cho đến nay tôi không phải là chuyên gia về C #, nhưng ít nhất trong các ngôn ngữ khác như Java và PHP, bạn có thể có một số loại từ điển, trong đó mỗi khóa có thể có giá trị như một từ điển khác.
Nicolás

Tôi cập nhật câu trả lời của tôi. Xem những gì bạn nghĩ về băm hoặc từ điển thay thế. Tôi cũng đã thêm một tài liệu tham khảo với một bài viết thú vị.
Nicolás

3

Một cách đơn giản để lưu trữ dữ liệu là chỉ nhồi dữ liệu vào cơ sở dữ liệu SQLite. SQLite, không giống như hầu hết các cơ sở dữ liệu SQL, rất phù hợp để sử dụng làm định dạng tệp ứng dụng. Cách tiếp cận này có một số lợi ích:

  1. Không cần mã hóa serializer hoặc deserializer.
  2. Tập tin có thể chỉnh sửa và truy vấn bởi nhiều chương trình hiện có.
  3. Sự lộn xộn có điều kiện bạn đề cập trong câu hỏi là tránh. Để hạn chế thả xuống, hãy tạo một mệnh đề where đơn giản đối với mỗi cột (ví dụ select distinct model where manufacturer='ford' and color = 'red':).

Điều này không bắt buộc bạn phải học SQL, nhưng tránh sự cần thiết phải học một định dạng tệp tùy chỉnh.


1

Tôi giả sử bạn có thể truy cập ngẫu nhiên các dòng trong tệp và do đó có thể coi tệp là một mảng các bản ghi. Nếu bạn không thể truy cập ngẫu nhiên các dòng, thì thuật toán bạn có là tốt nhất bạn có thể làm.

Để truy cập nhanh nhất, hãy lưu trữ dữ liệu trong 6 tệp, trong đó mỗi tệp là một chỉ mục vào tệp tiếp theo.

Có nhiều cách để tạo ra các chỉ số phẳng. Tôi thường sử dụng một phạm vi đăng ký. Khi người dùng thực hiện mỗi lựa chọn, hãy sử dụng phạm vi để giới hạn việc đọc tệp tiếp theo.

Đây là cách tôi sẽ tạo các chỉ mục cho dữ liệu mẫu bạn cung cấp.

Tất nhiên các tập tin phải được sắp xếp. Tôi đã đánh số các dòng để minh họa; số dòng không được xuất hiện trong tập tin.

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

Để tạo chỉ mục đầu tiên, tạo một bản ghi cho mỗi kết hợp duy nhất của ba trường đầu tiên trong tệp. Trong mỗi bản ghi, lưu trữ số dòng đầu tiên và cuối cùng trong đó kết hợp đó xuất hiệ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

Chỉ mục thứ hai được xây dựng tương tự, sử dụng hai trường đầu tiên của chỉ mục đầu tiên.

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

Và thứ ba, cấp cao nhất trong trường hợp này, chỉ số.

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

Tôi nghĩ rằng tôi đang giải thích quá mức khái niệm này, nhưng nói chung, bạn tạo một chỉ mục bằng cách bỏ trường cuối cùng và loại bỏ các bản ghi trùng lặp.

Bạn có thể giảm thêm yêu cầu lưu trữ tệp bằng cách loại bỏ một số dữ liệu dư thừa.

Ví dụ: chỉ số "đầu tiên" trong mỗi bản ghi chỉ số luôn luôn nhiều hơn một chỉ số "cuối cùng" của bản ghi trước hoặc bằng 0 nếu không có bản ghi trước. Vì vậy, bạn không cần lưu trữ các mục con "đầu tiên". Tôi để chúng ở vị trí dưới đây để minh họa.

Ngoài ra, vì bạn sẽ chỉ sử dụng trường cuối cùng trong mỗi bản ghi để điền vào danh sách lựa chọn, bạn không cần lưu trữ các trường khác.

Biểu hiện tối thiểu của tầng chỉ số kết thúc giống như thế này, trong đó dấu 'chỉ ra một số không thực sự được lưu trữ trong tệp.

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

Khi bạn điền vào danh sách lựa chọn từ một chỉ mục, bạn sử dụng các chỉ mục "đầu tiên" và "cuối cùng" từ lựa chọn của người dùng trong chỉ mục trước đó để giới hạn các dòng đã đọc.

Thí dụ:

Bạn điền vào danh sách lựa chọn đầu tiên từ tất cả file0.dat. (Ford, Subaru)

Người dùng chọn "Ford". Các chỉ số tương ứng là 0 và 1.

Bạn điền vào danh sách lựa chọn thứ hai từ dòng 0 đến 1 của file1.dat. (Xe tải, xe tải)

Người dùng chọn "Sedan". Các mục con tương ứng là 2 và 2.

Như bạn có thể thấy, vào thời điểm người dùng đã chọn, ví dụ: "Ford" "Sedan" "Taurus", bạn sẽ thấy rằng bạn chỉ cần đọc các dòng từ 6 đến 8 file3.datđể điền vào danh sách lựa chọn thứ tư.

Tôi xin lỗi vì mô tả khá dài nhưng ở đây rất muộn và tôi không có thời gian để viết một đoạn ngắn.

THÊM: Theo suy nghĩ thêm, các tập tin có thể được nối thành một.

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

Điều này được sử dụng chính xác như phiên bản nhiều tệp, ngoại trừ bạn cần dòng đầu tiên giả để chứa phạm vi đăng ký đầu tiên.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.