¿Cómo enumero JvMemoryData ... O, cómo creo un hash con una sola clave y múltiples valores?
-
03-07-2019 - |
Pregunta
Estoy usando JvMemoryData para rellenar un JvDBUltimGrid. Principalmente utilizo este JvMemoryData como una estructura de datos, porque no conozco nada que satisfaga mis necesidades.
No estoy trabajando con muchos datos, pero necesito una forma de enumerar los registros que estoy agregando a JvMemoryData. ¿Alguien ha hecho esto antes? ¿Sería posible de alguna manera " consultar " estos datos usando TSQLQuery?
O, ¿hay una mejor manera de hacer esto? Soy un poco ingenuo cuando se trata de estructuras de datos, por lo que tal vez alguien pueda señalarme en la dirección correcta. Lo que realmente necesito es como un diccionario / hash, que permite 1 clave y muchos valores. Al igual que:
KEY1: val1;val2;val3;val4;val5;etc...
KEY2: val1;val2;val3;val4;val5;etc...
Consideré usar THashedStringList en la unidad IniFiles, pero todavía sufre del mismo problema, ya que solo permite asociar 1 clave a un valor.
Solución
Una forma sería crear una TStringList, y hacer que el objeto de cada elemento apunte a otra TList (o TStringList) que contenga todos sus valores. Si la lista de cadenas superior está ordenada, entonces la recuperación está a solo una búsqueda binaria.
Para agregar elementos a su lista superior, use algo como lo siguiente (SList = TStringList):
Id := SList.AddObject( Key1, tStringList.Create );
InnerList := tStringList(SList.Objects[id]);
// for each child in list
InnerList.add( value );
Cuando sea el momento de desechar la lista, asegúrate de liberar también cada una de las listas internas.
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);
Otros consejos
No soy un programador de Delphi, pero ¿no podría simplemente usar una lista o matriz como valor para cada entrada hash? En terminología de Java:
Map<String,List>
Parece que ya estás usando Jedi. Jedi contiene clases que te permiten mapear cualquier cosa con cualquier cosa.
Echa un vistazo a esta pregunta relacionada .
He estado usando una matriz de cualquier tipo de registro definido arbitrariamente por el usuario complejo como caché junto con una TStringList o THashedStringList. Accedo a cada registro usando una clave. Primero reviso la lista de cadenas para una coincidencia. Si no coincide, obtengo el registro de la base de datos y lo puse en la matriz. Puse su índice de matriz en la lista de cadenas. Al usar los registros con los que estoy trabajando, así es como se ve mi código:
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;
He estado obteniendo acceso instantáneo de esta manera.
Jack