4

Các tập hợp là một cấu trúc dữ liệu có điểm bán hàng chính là chúng chỉ chứa một phần tử cho mỗi khóa. Túi thư giãn các ngữ nghĩa này và cho phép bạn tiết kiệm nhiều yếu tố; triển khai ETS của họ tuân theo API giống như các bộ.

Hãy đi sâu vào mã

Túi có thể chứa nhiều thành phần ánh xạ tới cùng một khóa (trường đầu tiên hoặc trường thứ n của bộ dữ liệu đại diện cho từng thành phần).

Khi bạn tra cứu một khóa, những gì được trả về sẽ không còn là một danh sách với một bộ dữ liệu duy nhất, mà là một danh sách các yếu tố phù hợp:

bags_contain_multiple_elements_for_each_key_test() ->
  Movies = ets:new(movies, [bag]),
  ets:insert(Movies, {"The day the Earth stood still", 1956}),
  ets:insert(Movies, {"The day the Earth stood still", 2010}),
  [{_, FirstInsertedYear}, {_, SecondInsertedYear}] = ets:lookup(Movies, "The day the Earth stood still"),
  ?assertEqual(1956, FirstInsertedYear),
  ?assertEqual(2010, SecondInsertedYear).

Thứ tự không được đảm bảo theo như tôi biết, vì việc triển khai nội bộ là một bản đồ băm.

Các túi trùng lặp là một biến thể khác cho phép các phần tử hoàn toàn giống nhau, không chỉ ánh xạ tới một khóa bằng nhau mà còn có giá trị bằng nhau.

duplicate_bags_contain_multiple_perfectly_equal_elements_for_each_key_test() ->
  Account= ets:new(account, [duplicate_bag]),
  ets:insert(Account, {credit, 200}),
  ets:insert(Account, {debit, 100}),
  ets:insert(Account, {credit, 300}),
  ets:insert(Account, {credit, 200}),
  Credits = ets:lookup(Account, credit),
  ?assertEqual(3, length(Credits)).

Trong ví dụ này, chúng tôi đang lưu trữ nhiều hoạt động tín dụng và ghi nợ trên một Tài khoản và vì các hoạt động này thường được sao chép, chúng tôi nên lưu trữ tất cả chúng. Không chỉ có thể có nhiều bộ tín dụng , mà còn có nhiều yếu tố {tín dụng, 200} (và thực tế có trong tài khoản ngân hàng thực do hoạt động định kỳ như nhận lương.)

Các khóa ở vị trí khác với yếu tố đầu tiên của mỗi bộ dữ liệu cho phép bạn tạo túi ngay cả với cấu trúc dữ liệu hiện có:

bags_different_key_positions_are_allowed_test() ->
  Movies = ets:new(movies, [bag, {keypos, 2}]),
  ets:insert(Movies, {"Star Wars", 1977}),
  ets:insert(Movies, {"Terminator", 1984}),
  ets:insert(Movies, {"B Movie", 1977}),
  MoviesOf1977 = ets:lookup(Movies, 1977),
  ?assertEqual(2, length(MoviesOf1977)).

Kiên trì

Có thể chuyển đổi các bộ và túi thành các cấu trúc dữ liệu liên tục, thậm chí bằng cách duy trì API hiện tại:

persistent_sets_can_be_created_test() ->
  dets:open_file(movies, [{type, set}]),
  dets:insert(movies, {"Star Wars", 1977}),
  dets:close(movies),
  % in new processes and times...
  dets:open_file(movies, []),
  [{_, Year}] = dets:lookup(movies, "Star Wars"),
  ?assertEqual(1977, Year).

Các thao tác chèn / 2 và tra cứu / 2 không thay đổi ngữ nghĩa của chúng; tuy nhiên, bây giờ họ đến từ gói dets. Một số thao tác bổ sung để mở và đóng cấu trúc DETS được giới thiệu.

Túi theo cùng một API:

persistent_bags_can_be_created_test() ->
  dets:open_file(movies, [{type, bag}]),
  dets:insert(movies, {"Star Wars", 1978}),
  dets:close(movies),
  % in new processes and times...
  dets:open_file(movies, []),
  Result = dets:lookup(movies, "Star Wars"),
  ?assertEqual(1, length(Result)).

Bổ sung, cấu hình tiện dụng có thể được chuyển qua open_file / 2. Ví dụ: bạn có thể chỉ định tên tệp cho cấu trúc dữ liệu để truy xuất nó sau này chỉ dựa trên tên tệp đó.

Kết luận

Để tránh phát minh lại bánh xe, điều quan trọng là phải hiểu cấu trúc dữ liệu nào mà ngôn ngữ cung cấp cho chúng tôi miễn phí. Sự bền bỉ thậm chí còn phức tạp hơn từ quan điểm về độ bền và tính nhất quán của ghi, và vì vậy nó phải luôn được gia công cho nền tảng nếu ứng dụng của bạn không phải là cơ sở dữ liệu.

|