Có một vài triển khai của một lớp băm hoặc từ điển trong kho lưu trữ tệp MathWorks File Exchange. Tất cả những gì tôi đã xem xét sử dụng dấu ngoặc đơn quá tải để tham chiếu chính, ví dụ:matlab subsref: {} với đối số chuỗi không thành công, tại sao?
d = Dict;
d('foo') = 'bar';
y = d('foo');
có vẻ như giao diện hợp lý. Mặc dù vậy, nếu bạn muốn dễ dàng có từ điển chứa từ điển khác, hãy sử dụng dấu ngoặc đơn {}
thay vì dấu ngoặc đơn, vì điều này cho phép bạn nhận được giới hạn cú pháp của MATLAB (tùy ý, dường như). nhiều niềng răng được cho phép, tức là
t{1}{2}{3} % is legal MATLAB
t(1)(2)(3) % is not legal MATLAB
vì vậy, nếu bạn muốn một cách dễ dàng có thể tự điển tổ trong từ điển,
dict{'key1'}{'key2'}{'key3'}
như là một thành ngữ phổ biến ở Perl và có thể và thường xuyên rất hữu ích trong các ngôn ngữ khác bao gồm cả Python, sau đó trừ khi bạn muốn sử dụng n-1
biến trung gian để trích xuất một mục từ điển n
lớp sâu, điều này có vẻ là một lựa chọn tốt. Và nó có vẻ dễ dàng để viết lại các hoạt động subsref
và subsasgn
của lớp học để làm điều tương tự cho {}
như trước đây họ đã làm cho ()
và mọi thứ sẽ hoạt động.
Trừ khi nó không xảy ra khi tôi thử.
Đây là mã của tôi. (Tôi đã giảm nó vào một trường hợp tối thiểu. Không từ điển thực tế được thực hiện ở đây, mỗi đối tượng có một chìa khóa và một giá trị, nhưng điều này là đủ để chứng minh vấn đề.)
classdef TestBraces < handle
properties
% not a full hash table implementation, obviously
key
value
end
methods(Access = public)
function val = subsref(obj, ref)
% Re-implement dot referencing for methods.
if strcmp(ref(1).type, '.')
% User trying to access a method
% Methods access
if ismember(ref(1).subs, methods(obj))
if length(ref) > 1
% Call with args
val = obj.(ref(1).subs)(ref(2).subs{:});
else
% No args
val = obj.(ref.subs);
end
return;
end
% User trying to access something else.
error(['Reference to non-existant property or method ''' ref.subs '''']);
end
switch ref.type
case '()'
error('() indexing not supported.');
case '{}'
theKey = ref.subs{1};
if isequal(obj.key, theKey)
val = obj.value;
else
error('key %s not found', theKey);
end
otherwise
error('Should never happen')
end
end
function obj = subsasgn(obj, ref, value)
%Dict/SUBSASGN Subscript assignment for Dict objects.
%
% See also: Dict
%
if ~strcmp(ref.type,'{}')
error('() and dot indexing for assignment not supported.');
end
% Vectorized calls not supported
if length(ref.subs) > 1
error('Dict only supports storing key/value pairs one at a time.');
end
theKey = ref.subs{1};
obj.key = theKey;
obj.value = value;
end % subsasgn
end
end
Sử dụng mã này, tôi có thể gán như mong đợi:
t = TestBraces;
t{'foo'} = 'bar'
(Và rõ ràng là công việc phân công từ đầu ra hiển thị mặc định cho t
.) vì vậy, subsasgn
xuất hiện để làm việc một cách chính xác.
Nhưng tôi không thể lấy giá trị (subsref
không hoạt động):
t{'foo'}
??? Error using ==> subsref
Too many output arguments.
Thông báo lỗi làm cho không có ý nghĩa với tôi, và một breakpoint tại dòng thực thi đầu tiên của handler subsref
của tôi là không bao giờ hit, do đó, ít nhất bề ngoài này trông giống như một vấn đề MATLAB, không phải là một lỗi trong mã của tôi.
Rõ ràng chuỗi đối số cho ()
subscript ngoặc được phép, vì điều này hoạt động tốt nếu bạn thay đổi mã để làm việc với ()
thay vì {}
. (Ngoại trừ khi đó bạn không thể tổ chức hoạt động subscript, đó là đối tượng của bài tập.)
Xem xét những gì tôi đang làm sai trong mã của mình, bất kỳ hạn chế nào khiến tôi không thể làm được triển khai các từ điển lồng nhau sẽ được đánh giá cao.
Tuyệt vời, hoạt động. Vâng, tôi muốn biết câu trả lời dài. – jmhl
Và cảm ơn câu trả lời dài. Tôi đã đoán nó là một cái gì đó dọc theo những dòng sau câu trả lời đầu tiên của bạn, và điều này làm rõ nó. Tuyệt vời, cảm ơn một lần nữa. – jmhl
Vì R2015b bạn nên thay thế quá tải hàm 'numArgumentsFromSubscript' - xem câu trả lời cho http://stackoverflow.com/questions/8713730/matlab-subsref-with-string-argument-fails-why và Mathworks page https: // www. mathworks.com/help/matlab/matlab_oop/overloading-numel-subsref-and-subsasgn.html. – nekomatic