How do I enumerate JvMemoryData…Or, how do I create a hash with a single key and multiple values?

StackOverflow https://stackoverflow.com/questions/607820

  •  03-07-2019
  •  | 
  •  

Question

I am using JvMemoryData to populate a JvDBUltimGrid. I'm primarily using this JvMemoryData as a data structure, because I am not aware of anything else that meets my needs.

I'm not working with a lot of data, but I do need a way to enumerate the records I am adding to JvMemoryData. Has anyone done this before? Would it be possible to somehow "query" this data using TSQLQuery?

Or, is there a better way to do this? I'm a bit naive when it comes to data structures, so maybe someone can point me in the right direction. What I really need is like a Dictionary/Hash, that allows for 1 key, and many values. Like so:

KEY1: val1;val2;val3;val4;val5;etc...
KEY2: val1;val2;val3;val4;val5;etc...

I considered using THashedStringList in the IniFiles unit, but it still suffers from the same problem in that it allows only 1 key to be associated with a value.

Was it helpful?

Solution

One way would be to create a TStringList, and have each item's object point to another TList (or TStringList) which would contain all of your values. If the topmost string list is sorted, then retrieval is just a binary search away.

To add items to your topmost list, use something like the following (SList = TStringList):

Id := SList.AddObject( Key1, tStringList.Create );
InnerList := tStringList(SList.Objects[id]);
// for each child in list
  InnerList.add( value );

When its time to dispose the list, make sure you free each of the inner lists also.

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);

OTHER TIPS

I'm not a Delphi programmer but couldn't you just use a list or array as the value for each hash entry? In Java terminology:

Map<String,List>

You already seem to be using Jedi. Jedi contains classes that allow you to map anything with anything.

Take a look at this related question.

I have been using an array of any arbitrarily complex user defined record types as a cache in conjunction with a TStringList or THashedStringList. I access each record using a key. First I check the string list for a match. If no match, then I get the record from the database and put it in the array. I put its array index into the string list. Using the records I am working with, this is what my code looks like:

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;

I have been getting seemingly instant access this way.

Jack

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top