Key/Value Pairs : Part Two

In part one of this post I showed the slightly sluggish but typically acceptable Key/Value pairs.

But if we are willing to forgo Internet Explorer compatibility, there is a newer JavaScript feature called Map. It is supported on all modern computer and mobile browsers, and it can speed up Key/Values while adding new capabilties, the ability for the value to be an EWB class (or a string, integer or function).

Here’s what the JavaScript would look like (using strings as the values in this example):

const map1 = new Map();

map1.set('0', 'foo');
map1.set(1, 'bar');

map1.set('dog','cat')
console.log(map1.get( 'dog'));
// expected output: "cat"
const iterator1 = map1.values();

console.log(iterator1.next().value);
// Expected output: "foo"

console.log(iterator1.next().value);
// Expected output: "bar"

Creating an EWB version looks like this to set/get and iterate through the list.

procedure TestMap;
var
  map1 : TJavaScriptMap;
  iterator1 : TIterator;
  i : integer;
begin
  map1 := TJavaScriptMap.Create;
  map1.set('0', 'foo');
  map1.set('1', 'bar');

  map1.set('dog','cat');

  output( 'Size of array : ' + IntToStr( map1.Size ));
  output(map1.get( 'dog'));
// expected output: "cat"
  if isie then begin
     output('Skipping iterator, IE does not implement it');
  end else begin
     output('Here is the complete list of names')
     iterator1 := map1.values();

     for i := 0 to map1.size - 1 do
        output(iterator1.next.value );
  end;

  map1.Free;
end;

Running through the same tests as in the previous post, the Map construct is many times faster. What took seconds now takes about a millisecond.

But more importantly, you can set and get EWB classes since variants can hold anything.

You will need the code that implements Tmap. Those who have purchased my Nice Toolkit will find it’s in the current release. But here it is if you don’t have my toolkit:

unit nicemap;

interface

uses webcore, webdom;

type
 external TIterator = class( TExternalObject )
 public
   property Entries : array of variant read write;
   property value : variant read ;
   function next : TIterator;

 end;

 external TInternalMap = class (TExternalObject )
 public
    property size : integer read;
    procedure set( name : string; value : variant );
    function get( name : string ) : variant;
    function values : TIterator;    // iterator
  end;

  TJavaScriptMap = class( TOBject )
  private
    internalmap : TInternalMap;
  public
    constructor create ;
    destructor destroy;
    function get( name : string ):variant;
    procedure set( name : string ; value : variant );
    function values : TIterator;
    function size: integer;
  end;


implementation

constructor TJavaScriptMap.create;
begin
  internalmap := TInternalMap(CreateObject('new Map()'));
end;

destructor TJavaScriptMap.destroy;
begin
  internalmap.free;
end;

function TJavaScriptMap.size:integer;
begin
  result := internalmap.size;
end;

procedure TJavaScriptMap.Set( name : string ; value : variant );
begin
  internalmap.set( name, value );
end;

function TJavaScriptMap.Get( name : string ):variant;
begin
  result := internalmap.get( name );
end;

function TJavaScriptMap.values : TIterator;
begin
   result := internalmap.values;
end;
end.