Posts

Showing posts from June, 2010

Deleting elements from a dynamic array

In my blog "Initialising Dynamic Arrays" I mentioned I have been writing some unit tests that needed numerous repetative array initialisation operations. Well, one of the other common operations I found myself writing was the deletion of items from dynamic arrays. So I decided to find a generic way of doing this.Assuming we know the index of the item to be deleted we need the equivalent of Delphi's built-in Delete procedure for strings. If you read the previous post you won't be surprised to learn that I decided to further extend the Generics.Collections.TArray class by adding to the TArrayEx class I introduced there.My first attempt emulates Delphi's Delete procedure by deleting the array element in-place: i.e. it updates the array passed as a parameter. Unsurprisingly the method is called DeleteInPlace. Here's how it goes:typeTArrayEx=class(TArray)public...classprocedureDeleteInPlace<T>(varA:TArray<T>;constIndex:Integer);end;...classprocedureTAr…

Initialising dynamic arrays

When writing some unit tests a while ago I found myself needing to initialise some dynamic arrays with test data. It would be nice if we could do something like this:varA:arrayofInteger;beginA:=(1,2,3,4);// !! WRONGend; but we can't. So I decided to write some functions to initialise dynamic arrays to the contents of another array, be it a constant, a literal or another dynamic array.The result was a set of overloaded routines, one for each data type I needed to handle, for example for Integer and string arrays I had:functionCloneArray(constA:arrayofInteger):TIntegerDynArray;overload;varIdx:Integer;beginSetLength(Result,Length(A));forIdx:=Low(A)toHigh(A)doResult[Idx-Low(A)]:=A[Idx];end;functionCloneArray(constA:arrayofstring):TStringDynArray;overload;varIdx:Integer;beginSetLength(Result,Length(A));forIdx:=Low(A)toHigh(A)doResult[Idx-Low(A)]:=A[Idx];end; Noticing how similar these functions were - only the first line differs - I decided to try a generic approach. Since I didn't w…

Being dim #2: No generic global procedures

The other day I was writing some unit tests and needed some helper functions to look up some array elements of in arrays of different base types. I had several overloaded functions to do the job, like this:functionIndexOf(constItem:string;constA:arrayofstring):Integer;overload;functionIndexOf(constItem:Integer;constA:arrayofInteger):Integer;overload; Oh, I thought, generics are a way round this, so I replaced the overloaded functions with something likefunctionIndexOf<T>(constItem:T;constA:arrayofT):Integer; only to be get compiler error 2530: Type parameters not allowed on global procedure or function. Now, I didn't know that and I'm sharing it in case some of you didn't either.And the solution? I sorted it by using a static class to hold the code, i.e.typeTSomeClass=class(TObject)publicclassfunctionIndexOf<T>(constItem:T;constA:arrayofT):Integer;end; This works fine.I've not provided implementation details of any of this code since the details are not import…

Being dim #1: Array and set enumerators

One of my favourite additions to Delphi over the past years has been the for..in construct and the associated enumerators. I just love the way we can dovarCh:Char;S:string;beginS:='Some text';forChinSdo// Do something with Chend; So how come I missed that enumerators work on sets and arrays? I'm mentioning this here just in case it's slipped past anyone else, and in case you can tell me about any other enumerators I might have missed!Since forever I've being having to do stuff like this for arrays and sets:constcMyArray:array[1..4]ofByte=(51,60,80,81);cMySet:setofByte=[50,51,80,81,40,30,32];varI:Integer;B:Byte;beginforB:=Low(Byte)toHigh(Byte)doifBincMySetthen// Do stuff with BforI:=Low(cMyArray)toHigh(cMyArray)do// Do stuff my cMyArray[I]end; When all along I could have been doing:constcMyArray:array[1..4]ofByte=(51,60,80,81);cMySet:setofByte=[50,51,80,81,40,30,32];varItem:Byte;beginforItemincMySetdo// Do stuff with ItemforItemincMyArraydo// Do stuff with Itemend; Duh…