Come posso enumerare JvMemoryData & # 8230; Oppure, come posso creare un hash con una sola chiave e più valori?
-
03-07-2019 - |
Domanda
Sto usando JvMemoryData per popolare un JvDBUltimGrid. Sto principalmente usando questo JvMemoryData come struttura di dati, perché non sono a conoscenza di nient'altro che soddisfi le mie esigenze.
Non sto lavorando con molti dati, ma ho bisogno di un modo per enumerare i record che sto aggiungendo a JvMemoryData. Qualcuno l'ha già fatto? Sarebbe possibile in qualche modo "interrogare" questi dati utilizzando TSQLQuery?
O c'è un modo migliore per farlo? Sono un po 'ingenuo quando si tratta di strutture di dati, quindi forse qualcuno può indicarmi la giusta direzione. Quello di cui ho davvero bisogno è come un dizionario / hash, che consenta 1 chiave e molti valori. In questo modo:
KEY1: val1;val2;val3;val4;val5;etc...
KEY2: val1;val2;val3;val4;val5;etc...
Ho pensato di utilizzare THashedStringList nell'unità IniFiles, ma soffre ancora dallo stesso problema in quanto consente solo 1 chiave da associare a un valore.
Soluzione
Un modo sarebbe quello di creare una TStringList e fare in modo che l'oggetto di ciascun elemento punti a un'altra TList (o TStringList) che conterrebbe tutti i tuoi valori. Se viene ordinato l'elenco di stringhe più in alto, il recupero è solo una ricerca binaria.
Per aggiungere elementi al tuo elenco più in alto, usa qualcosa come il seguente (SList = TStringList):
Id := SList.AddObject( Key1, tStringList.Create );
InnerList := tStringList(SList.Objects[id]);
// for each child in list
InnerList.add( value );
Quando è il momento di disporre dell'elenco, assicurati di liberare anche ciascuno degli elenchi interni.
for i := 0 to SList.count-1 do
begin
if Assigned(SList.Objects[i]) then
SList.Objects[i].free;
SList.Objects[i] := nil;
end;
FreeAndNil(SList);
Altri suggerimenti
Non sono un programmatore Delphi ma non potresti semplicemente usare un elenco o un array come valore per ogni voce hash? Nella terminologia Java:
Map<String,List>
Sembra che tu stia già usando Jedi. Jedi contiene classi che ti consentono di mappare qualsiasi cosa con qualsiasi cosa.
Dai un'occhiata a questa domanda correlata .
Ho usato un array di qualsiasi tipo di record definito dall'utente arbitrariamente complesso come cache insieme a TStringList o THashedStringList. Accedo a ogni record usando una chiave. Per prima cosa controllo l'elenco delle stringhe per una corrispondenza. Se nessuna corrispondenza, quindi ottengo il record dal database e lo inserisco nella matrice. Ho inserito il suo indice di array nell'elenco delle stringhe. Usando i record con cui sto lavorando, ecco come appare il mio codice:
function TEmployeeCache.Read(sCode: String): TEmployeeData;
var iRecNo: Integer;
oEmployee: TEmployee;
begin
iRecNo := CInt(CodeList.Values[sCode]);
if iRecNo = 0 then begin
iRecNo := FNextRec;
inc(FNextRec);
if FNextRec > High(Cache) then SetLength(Cache, FNextRec * 2);
oEmployee := TEmployee.Create;
oEmployee.Read(sCode);
Cache[iRecNo] := oEmployee.Data;
oEmployee.Free;
KeyList.Add(Format('%s=%s', [CStr(Cache[iRecNo].hKey), IntToStr(iRecNo)]));
CodeList.Add(Format('%s=%s', [sCode, IntToStr(iRecNo)]));
end;
Result := Cache[iRecNo];
end;
Sto ottenendo un accesso apparentemente immediato in questo modo.
Jack