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