Posts

Concatenating Dynamic Arrays

Another day another unit test and another extension to my little TArrayEx class. This time I found myself having to concatenate some dynamic arrays. After solving the problem for the particular array type I decided to produce a generic solution. Here's the method I came up with: type TArrayEx = class ( TObject ) public .. . class function Concat < T > ( const Arrays : array of TArray < T > ) : TArray < T > ; .. . end ; The method takes an array of the arrays you want to concatenate (don't forget the [] notation) and returns the concatenated array. Here's an example where the resultant array A contains the integers 1 to 10 in order: var A , A1 , A2 , A3 : TArray < Integer > ; begin A1 := TArray < Integer > . Create ( 1 , 2 , 3 ) ; A2 := TArray < Integer > . Create ( 4 , 5 , 6 ) ; A3 := TArray < Integer > . Create ( 7 , 8 , 9 , 10 ) ; A := TArrayEx . Conc...

DelphiDabbler Code Library help

Some users of the components and units from the DelphiDabbler Code Library have contacted me to ask if the library's help is available in HTML help format because WinHelp format I used for the library won't work by default on Windows Vista and later. The answer is no - and I don't have time to do the conversions. However, all is not lost because there is now a Wiki for each of the Code Library projects hosted on Google Code. In future the Wikis will be updated in preference to the old WinHelp help files. View the list of available Wikis . Source code highlighting by DelphiDabbler PasHi .

Initialising dynamic arrays - take 2

In my earlier post on this subject I presented some methods to use to initialise and clone dynamic arrays. Some comments to that post suggested a simpler approach using compiler features I didn't know existed. In this post I've simply collected the information from those comments together in one place. To initialise an array from literal values you can use the special array constructor provided by the compiler: uses Types ; var A : TIntegerDynArray ; begin A := TIntegerDynArray . Create ( 1 , 2 , 3 , 4 ) ; .. . end ; This also works when you define your own array types, for example: var TMyByteArray = array of Byte ; begin A := TMyByteArray . Create ( 1 , 2 , 3 , 4 ) ; .. . end ; And it also works for the TArray<T> generic array type: var IntArray : TArray < Integer > ; StrArray : TArray < string > ; begin IntArray := TArray < Integer > . Create ( 1 , 2 , 3 ) ; StrArray := TAr...

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: type TArrayEx = class ( TArray ) public .. . class procedure DeleteInPlace < T > ( var A : ...

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: var A : array of Integer ; begin A := ( 1 , 2 , 3 , 4 ) ; // !! WRONG end ; 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: function CloneArray ( const A : array of Integer ) : TIntegerDynArray ; overload ; var Idx : Integer ; begin SetLength ( Result , Length ( A ) ) ; for Idx := Low ( A ) to High ( A ) do Result [ Idx - Low ( A ) ] := A [ Idx ] ; end ; function CloneArray ( const A : array of string ) : TStringDynArray ; overload ; var Idx : Integer ; begin SetLength ( Result , Len...

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: function IndexOf ( const Item : string ; const A : array of string ) : Integer ; overload ; function IndexOf ( const Item : Integer ; const A : array of Integer ) : Integer ; overload ; Oh, I thought, generics are a way round this, so I replaced the overloaded functions with something like function IndexOf < T > ( const Item : T ; const A : array of T ) : 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. type TSomeClass = class ( TObject ) public class function IndexOf < T > ( const Ite...

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 do var Ch : Char ; S : string ; begin S := 'Some text' ; for Ch in S do // Do something with Ch end ; 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: const cMyArray : array [ 1 .. 4 ] of Byte = ( 51 , 60 , 80 , 81 ) ; cMySet : set of Byte = [ 50 , 51 , 80 , 81 , 40 , 30 , 32 ] ; var I : Integer ; B : Byte ; begin for B := Low ( Byte ) to High ( Byte ) do if B in cMySet then // Do stuff with B for I := Low ( cMyArray ) to High ( cMyArray ) do // Do stuff my cMyArray[I] end ; ...