Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- program Project1;
- {$APPTYPE CONSOLE}
- {$R *.res}
- uses
- System.SysUtils, System.Generics.Collections, System.Math, System.Diagnostics, System.Generics.Defaults,
- SynCommons;
- type
- TDataLine = class
- SeqNo: integer;
- TransactionID: integer;
- CustomName: string;
- end;
- TDataLineArray = array of TDataLine;
- TDataLookup = class
- var
- fData: TObjectList<TDataLine>;
- fDataByID: TDictionary<integer, TDataLine>;
- fDataByName: TDictionary<string, TDataLine>;
- fSortedById: TArray<TDataLine>;
- fSortedByName: TArray<TDataLine>;
- fSynIDs: TSynDictionary;
- fSynNames: TSynDictionary;
- public
- constructor Create;
- procedure SortByID;
- procedure SortByName;
- procedure Add(aTransID: integer; const aName: string);
- function Count: integer;
- function GetAllIDs: TArray<integer>;
- function GetAllNames: TArray<string>;
- // Sequenced
- function GetDataName(aID: integer): string;
- function GetDataID(const aName: string): integer;
- function Exists(aID: integer; const aName: string): boolean;
- // Dictionary
- function GetNameFromDictionary(aID: integer): string;
- function GetIDFromDictionary(const aName: string): integer;
- // TSynDictionary
- function GetNameFromSyn(aID: integer): string;
- function GetIDFromSyn(const aName: string): integer;
- // Sorted - TArray.BinarySearch
- function GetNameFromSorted(aID: integer): string;
- function GetIDFromSorted(const aName: string): integer;
- end;
- var
- gDataLookup: TDataLookup;
- constructor TDataLookup.Create;
- begin
- fData := TObjectList<TDataLine>.Create;
- fDataByID := TDictionary<integer, TDataLine>.Create;
- fDataByName := TDictionary<string, TDataLine>.Create;
- fSynIDs := TSynDictionary.Create(TypeInfo(TIntegerDynArray), TypeInfo(TDataLineArray));
- fSynNames := TSynDictionary.Create(TypeInfo(TStringDynArray), TypeInfo(TDataLineArray));
- end;
- function TDataLookup.Count: integer;
- begin
- Result := fData.Count;
- end;
- procedure TDataLookup.SortByID;
- var
- i: Integer;
- begin
- SetLength(fSortedById, fData.Count);
- for i := 0 to Pred(fData.Count) do
- begin
- fSortedById[i] := TDataLine.Create;
- fSortedById[i].TransactionID := fData.List[i].TransactionID;
- fSortedById[i].CustomName := fData.List[i].CustomName;
- end;
- TArray.Sort<TDataLine>(fSortedById,
- TDelegatedComparer<TDataLine>.Construct(
- function(const Left, Right: TDataLine): Integer
- begin
- if Left.TransactionID > Right.TransactionID then Exit(1);
- if Left.TransactionID < Right.TransactionID then Exit(-1);
- Result:= 0;
- end));
- end;
- procedure TDataLookup.SortByName;
- var
- i: Integer;
- begin
- SetLength(fSortedByName, fData.Count);
- for i := 0 to Pred(fData.Count) do
- begin
- fSortedByName[i] := TDataLine.Create;
- fSortedByName[i].TransactionID := fData.List[i].TransactionID;
- fSortedByName[i].CustomName := fData.List[i].CustomName;
- end;
- TArray.Sort<TDataLine>(fSortedByName,
- TDelegatedComparer<TDataLine>.Construct(
- function(const Left, Right: TDataLine): Integer
- begin
- Result := CompareStr(Left.CustomName, Right.CustomName);
- end));
- end;
- procedure TDataLookup.Add(aTransID: integer; const aName: string);
- var vData: TDataLine;
- begin
- vData := TDataLine.Create;
- vData.TransactionID := aTransID;
- vData.CustomName := aName;
- vData.SeqNo := fData.Count + 1;
- fData.Add(vData);
- fDataByID.Add(vData.TransactionID, vData);
- fDataByName.Add(vData.CustomName, vData);
- fSynIDs.Add(vData.TransactionID, vData);
- fSynNames.Add(vData.CustomName, vData);
- end;
- function TDataLookup.GetDataName(aID: integer): string;
- var
- i: integer;
- begin
- Result := '';
- for i := 0 to Pred(fData.Count) do
- if fData[i].TransactionID = aId then
- Exit(fData[i].CustomName);
- end;
- function TDataLookup.GetNameFromDictionary(aID: integer): string;
- var vDataLine: TDataLine;
- begin
- if fDataByID.TryGetValue(aID, vDataLine) then
- Result := vDataLine.CustomName;
- end;
- function TDataLookup.GetIDFromDictionary(const aName: string): integer;
- var vDataLine: TDataLine;
- begin
- Result := 0;
- if fDataByName.TryGetValue(aName, vDataLine) then
- Result := vDataLine.TransactionID;
- end;
- function TDataLookup.GetNameFromSyn(aID: integer): string;
- var vDataLine: TDataLine;
- begin
- vDataLine := TDataLine(fSynIDs.FindValue(aID)^);
- Result := vDataLine.CustomName;
- end;
- function TDataLookup.GetIDFromSyn(const aName: string): integer;
- var vDataLine: TDataLine;
- begin
- vDataLine := TDataLine(fSynNames.FindValue(aName)^);
- Result := vDataLine.TransactionID;
- end;
- function BinarySearchByID(const aData: TArray<TDataLine>; const aID: integer): integer;
- var L, H, i, c: Integer;
- begin
- Result := 0;
- L := 0; H := High(aData);
- while L <= H do
- begin
- i := L + (H - L) shr 1;
- c := CompareValue(aData[i].TransactionID, aID);
- if c < 0 then
- L := i + 1
- else
- begin
- if c = 0 then
- Exit(i);
- H := i - 1;
- end;
- end;
- end;
- function BinarySearchByName(const aData: TArray<TDataLine>; const aName: string): integer;
- var L, H, i, c: Integer;
- begin
- Result := 0;
- L := 0; H := High(aData);
- while L <= H do
- begin
- i := L + (H - L) shr 1;
- c := CompareStr(aData[i].CustomName, aName);
- if c < 0 then
- L := i + 1
- else
- begin
- if c = 0 then
- Exit(aData[i].TransactionID);
- H := i - 1;
- end;
- end;
- end;
- function TDataLookup.GetNameFromSorted(aID: integer): string;
- var vDataLine: TDataLine;
- vIdx: integer;
- begin
- vDataLine := TDataLine.Create;
- vDataLine.TransactionID := aID;
- if TArray.BinarySearch<TDataLine>(fSortedById, vDataLine, vIdx,
- TComparer<TDataLine>.Construct(
- function (const Left, Right: TDataLine): Integer
- begin
- if Left.TransactionID < Right.TransactionID then
- Result := -1
- else if Left.TransactionID > Right.TransactionID then
- Result := 1
- else
- Result := 0;
- end
- ))
- then
- Result := fSortedById[vIdx].CustomName;
- end;
- function TDataLookup.GetIDFromSorted(const aName: string): integer;
- var vDataLine: TDataLine;
- vIdx: integer;
- begin
- Result := 0;
- vDataLine := TDataLine.Create;
- vDataLine.CustomName := aName;
- if TArray.BinarySearch<TDataLine>(fSortedByName, vDataLine, vIdx,
- TComparer<TDataLine>.Construct(
- function (const Left, Right: TDataLine): Integer
- begin
- Result := CompareStr(Left.CustomName, Right.CustomName)
- end
- ))
- then
- Result := fSortedByName[vIdx].TransactionID;
- end;
- function TDataLookup.GetDataID(const aName: string): integer;
- var
- i: integer;
- begin
- Result := 0;
- for i := 0 to Pred(fData.Count) do
- if fData[i].CustomName = aName then
- Exit(fData[i].TransactionID);
- end;
- function TDataLookup.Exists(aID: integer; const aName: string): boolean;
- var
- i: Integer;
- begin
- Result := false;
- for i := 0 to Pred(fData.Count) do
- if (fData[i].TransactionID = aId) or (fData[i].CustomName = aName) then
- Exit(True);
- end;
- function TDataLookup.GetAllIDs: TArray<integer>;
- var
- i: Integer;
- begin
- SetLength(Result, fData.Count);
- for i := 0 to Pred(fData.Count) do
- Result[i] := fData.List[i].TransactionID;
- end;
- function TDataLookup.GetAllNames: TArray<string>;
- var
- i: Integer;
- begin
- SetLength(Result, fData.Count);
- for i := 0 to Pred(fData.Count) do
- Result[i] := fData.List[i].CustomName;
- end;
- const
- cChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
- function GetRandomString(aNoOfChars: integer): string;
- var i: Integer;
- begin
- SetLength(Result, aNoOfChars);
- for i := 1 to aNoOfChars do
- Result[i] := cChars[Random(Length(cChars)) + 1];
- end;
- procedure GetRandomDataLine(out aTransID: integer; out aCustomName: string);
- begin
- aTransId := Random(maxint);
- aCustomName := GetRandomString(RandomRange(12, 30));
- end;
- procedure CreateRandomData(var aDataLookup: TDataLookup; aCount: integer);
- var
- c: Integer;
- vTransID: integer;
- vCustomName: string;
- begin
- aDataLookup := TDataLookup.Create;
- c := 0;
- while c < aCount do
- begin
- GetRandomDataLine(vTransID, vCustomName);
- if Not aDataLookup.Exists(vTransID, vCustomName) then
- begin
- aDataLookup.Add(vTransID, vCustomName);
- inc(c);
- end;
- end;
- end;
- const
- cMaxLoop: integer = 1000000;
- cRunRecords: array of integer = [10, 50, 100, 1000, 10000];
- var vArrayOfIDs: TArray<integer>;
- vArrayOfNames: TArray<string>;
- var a, i, vNoOfRecs, vTiming_u, vTiming_d, vTiming_s, vTiming_bs, vTiming_syn: integer;
- vName: string;
- vID: integer;
- vSW: TStopWatch;
- begin
- Randomize;
- Writeln('Get Name from ID (Search by integer):');
- Writeln('records Sequenced TArray.BinS TDict CustomBinS TSynDict');
- for vNoOfRecs in cRunRecords do
- begin
- CreateRandomData(gDataLookup, vNoOfRecs);
- try
- vArrayOfIDs := gDataLookup.GetAllIDs;
- // Sequenced
- vSW := TStopWatch.StartNew;
- for a := 1 to cMaxLoop div vNoOfRecs do
- for i := Low(vArrayOfIDs) to High(vArrayOfIDs) do
- vName := gDataLookup.GetDataName(vArrayOfIDs[i]);
- vTiming_u := vSW.ElapsedMilliseconds;
- // Sorted - TArray.BinarySearch
- gDataLookup.SortByID;
- vSW := TStopWatch.StartNew;
- for a := 1 to cMaxLoop div vNoOfRecs do
- for i := Low(vArrayOfIDs) to High(vArrayOfIDs) do
- vName := gDataLookup.GetNameFromSorted(vArrayOfIDs[i]);
- vTiming_s := vSW.ElapsedMilliseconds;
- // Dictionary
- vSW := TStopWatch.StartNew;
- for a := 1 to cMaxLoop div vNoOfRecs do
- for i := Low(vArrayOfIDs) to High(vArrayOfIDs) do
- vName := gDataLookup.GetNameFromDictionary(vArrayOfIDs[i]);
- vTiming_d := vSW.ElapsedMilliseconds;
- //BinarySearch
- gDataLookup.SortByID;
- vSW := TStopWatch.StartNew;
- for a := 1 to cMaxLoop div vNoOfRecs do
- for i := Low(vArrayOfIDs) to High(vArrayOfIDs) do
- vName := gDataLookup.fSortedById[BinarySearchByID(gDataLookup.fSortedById, vArrayOfIDs[i])].CustomName;
- vTiming_bs := vSW.ElapsedMilliseconds;
- // Syn
- vSW := TStopWatch.StartNew;
- for a := 1 to cMaxLoop div vNoOfRecs do
- for i := Low(vArrayOfIDs) to High(vArrayOfIDs) do
- vName := gDataLookup.GetNameFromSyn(vArrayOfIDs[i]);
- vTiming_syn := vSW.ElapsedMilliseconds;
- Writeln(Format('%5s %5s %4s %4s %4s %4s',[vNoOfRecs.ToString, vTiming_u.ToString, vTiming_s.ToString, vTiming_d.ToString, vTiming_bs.ToString, vTiming_syn.ToString]));
- finally
- FreeAndNil(gDataLookup);
- end;
- end;
- Writeln;
- Writeln('Get ID from Name (Search by string):');
- Writeln('records Sequenced TArray.BinS TDict CustomBinS TSynDict');
- for vNoOfRecs in cRunRecords do
- begin
- CreateRandomData(gDataLookup, vNoOfRecs);
- try
- vArrayOfNames := gDataLookup.GetAllNames;
- // Sequenced
- vSW := TStopWatch.StartNew;
- for a := 1 to cMaxLoop div vNoOfRecs do
- for i := Low(vArrayOfNames) to High(vArrayOfNames) do
- vID := gDataLookup.GetDataID(vArrayOfNames[i]);
- vTiming_u := vSW.ElapsedMilliseconds;
- // Sorted - TArray.BinarySearch
- gDataLookup.SortByName;
- vSW := TStopWatch.StartNew;
- for a := 1 to cMaxLoop div vNoOfRecs do
- for i := Low(vArrayOfNames) to High(vArrayOfNames) do
- vID := gDataLookup.GetIDFromSorted(vArrayOfNames[i]);
- vTiming_s := vSW.ElapsedMilliseconds;
- // Dictionary
- vSW := TStopWatch.StartNew;
- for a := 1 to cMaxLoop div vNoOfRecs do
- for i := Low(vArrayOfNames) to High(vArrayOfNames) do
- vID := gDataLookup.GetIDFromDictionary(vArrayOfNames[i]);
- vTiming_d := vSW.ElapsedMilliseconds;
- //BinarySearch
- gDataLookup.SortByName;
- vSW := TStopWatch.StartNew;
- for a := 1 to cMaxLoop div vNoOfRecs do
- for i := Low(vArrayOfNames) to High(vArrayOfNames) do
- vID := BinarySearchByName(gDataLookup.fSortedByName, vArrayOfNames[i]);
- vTiming_bs := vSW.ElapsedMilliseconds;
- //Syn
- vSW := TStopWatch.StartNew;
- for a := 1 to cMaxLoop div vNoOfRecs do
- for i := Low(vArrayOfNames) to High(vArrayOfNames) do
- vID := gDataLookup.GetIDFromSyn(vArrayOfNames[i]);
- vTiming_syn := vSW.ElapsedMilliseconds;
- Writeln(Format('%5s %5s %4s %4s %4s %4s',[vNoOfRecs.ToString, vTiming_u.ToString, vTiming_s.ToString, vTiming_d.ToString, vTiming_bs.ToString, vTiming_syn.ToString]));
- finally
- FreeAndNil(gDataLookup);
- end;
- end;
- Writeln;
- Writeln('done...');
- readln;
- end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement