Esistono alcune implementazioni di una classe hash o dizionario nel repository di Scambio file di Mathworks. Tutto ciò che ho visto utilizza l'overloading delle parentesi per la referenziazione delle chiavi, ad es.sottosuolo MATLAB: {} con argomento stringa fallisce, perché?
d = Dict;
d('foo') = 'bar';
y = d('foo');
che sembra un'interfaccia ragionevole. Sarebbe preferibile, tuttavia, se si desidera avere facilmente dizionari che contengono altri dizionari, utilizzare le parentesi graffe {}
anziché parentesi, in quanto ciò consente di aggirare la limitazione della sintassi di MATLAB (arbitraria, sembra) che non sono consentite più parentesi ma multiple parentesi graffe sono consentiti, cioè
t{1}{2}{3} % is legal MATLAB
t(1)(2)(3) % is not legal MATLAB
Quindi, se si vuole essere facilmente in grado di dizionari nido all'interno di dizionari,
dict{'key1'}{'key2'}{'key3'}
come è un idioma comune in Perl ed è possibile e spesso utile in altre lingue incluso Python, quindi a meno che non si voglia utilizzare n-1
variabili intermedie per estrarre una voce dizionario n
livelli profondi, questa sembra una buona scelta. E sembrerebbe facile riscrivere le operazioni della classe subsref
e subsasgn
per fare la stessa cosa per {}
come hanno fatto in precedenza per ()
e tutto dovrebbe funzionare.
Tranne che non quando lo provo.
Ecco il mio codice. (Ho ridotto a un caso di minima. Nessun dizionario vero e proprio è implementato qui, ogni oggetto ha una chiave e un valore, ma questo è sufficiente per dimostrare il problema.)
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
Utilizzando questo codice, posso assegnare come previsto:
t = TestBraces;
t{'foo'} = 'bar'
(Ed è chiaro che il lavoro di assegnazione dall'uscita di visualizzazione predefinita per t
.) Così subsasgn
sembra funzionare correttamente.
Ma non riesco a recuperare il valore (subsref
non funziona):
t{'foo'}
??? Error using ==> subsref
Too many output arguments.
Il messaggio di errore non ha senso per me, e un punto di interruzione nella prima riga eseguibile del mio subsref
gestore non è mai colpire, quindi almeno superficialmente questo sembra un problema di MATLAB, non un bug nel mio codice.
Chiaramente argomenti stringa a ()
pedice parentesi sono autorizzati, dal momento che questo funziona bene se si modifica il codice per lavorare con ()
invece di {}
. (Tranne che non è possibile nidificare le operazioni di pedice, che è l'oggetto dell'esercizio.)
O intuizione su cosa sto facendo male nel mio codice, eventuali limitazioni che rendono ciò che sto facendo non fattibile, o alternativa le implementazioni dei dizionari nidificati sarebbero apprezzate.
Ottimo, funziona. Sì, mi piacerebbe conoscere la lunga risposta. – jmhl
E grazie per la lunga risposta. Immagino che fosse qualcosa di simile dopo la tua prima risposta, e questo lo chiarisce. Ottimo, grazie ancora. – jmhl
Dato che R2015b dovresti invece sovraccaricare la funzione 'numArgumentsFromSubscript' - vedi le risposte a http://stackoverflow.com/questions/8713730/matlab-subsref-with-string-argument-fails-why e la pagina di Mathworks https: // www. mathworks.com/help/matlab/matlab_oop/overloading-numel-subsref-and-subsasgn.html. – nekomatic