13

When I approach Java problems, I use the collection pattern. However, doing it in Delphi is quite a nightmare since there is no Integer object to handle things.

I need a data structure that holds numbers. I want to be able to add numbers, remove numbers, and check the contents of the collection, and each number must be unique.

I'm not interested in a solution I need to implement and test for bugs myself. Is there a ready object like Java's HashTable?

none
  • 4,669
  • 14
  • 62
  • 102

9 Answers9

22
uses GpLists;

var
  numberList: TGpIntegerList;
begin
  numberList := TGpIntegerList.Create;
  numberList.Duplicates := dupIgnore;
  numberList.Sorted := true;
  numberList.add(1);
  numberList.add(2);
  numberList.add(3);
  numberList.add(1);

GpLists comes with a BSD license. It also contains a class holding 64-bit integers - TGpInt64List - and bunch of other stuff.

gabr
  • 26,580
  • 9
  • 75
  • 141
  • `GPLists` is also contained in the **OmniThreadLibrary** that can be found in the Delphi GetIt Package Manager. – user1580348 Feb 20 '21 at 15:23
12

Dictionary<Integer,Boolean> or similar would do.

Barry Kelly
  • 41,404
  • 5
  • 117
  • 189
9

I know it's dirty, but you could misuse TStringList (or THashedStringList).

var
  numberList: TStringList;
begin
  numberList := TStringList.Create;
  numberList.Duplicates := dupIgnore;
  numberList.Sorted := true;
  numberList.add(IntToStr(1));
  numberList.add(IntToStr(2));
  numberList.add(IntToStr(3));
  numberList.add(IntToStr(1));
  // numberList.CommaText = '1,2,3'
splash
  • 13,037
  • 1
  • 44
  • 67
  • 1
    i dont want to be able to mistake it with other strings. baah, i guess it would do. Bad Delphi. Edit: took me less time then i though. THANKS!!! – none Oct 12 '10 at 12:14
  • 4
    @none, implementing your custom TIntegerList should take only some minutes. – splash Oct 12 '10 at 12:15
  • 3
    I would just use a TList instead of a TStringList, casting integer to pointer. If I had a recent Delphi version (>= 2009) I probably would use a TList. – The_Fox Oct 12 '10 at 12:19
  • 1
    @The_Fox: `TList` could be used for the custom implementation of an `TIntegerList` class, but it doesn't comes with an built-in duplicate check. – splash Oct 12 '10 at 12:24
  • It doesn't sort correclty by default. And Duplicates needs the list to be sorted. –  Oct 12 '10 at 12:27
  • 1
    @ldsandon, although it doesn't sort in numeric order, `Duplicates` doesn't need the list to be sorted numerically. It just needs to be sorted consistently, which this list will do just fine. – Rob Kennedy Oct 12 '10 at 13:00
  • @splash, yes, you have to do that manually with a TList. The best solution is like you said creating an own TIntegerList implementation. – The_Fox Oct 12 '10 at 13:01
  • @Kennedy: I was not implying it wouldn't work - just that iterating the list would get the numbers in the wrong order. And if you need to check for duplicates you need to enable sorting, and thereby you can't use other orderings (i.e how they were insterted). Didn't check anyway if the sorting algorithm of a TStringList can be changed - never had a reason to do it. –  Oct 12 '10 at 18:36
  • @splash but testing my implementation of custom TIntegerList should take several days. – none May 01 '11 at 08:56
  • @none: I would say to test a `TIntegerList` would take several weeks! ;-) – splash May 02 '11 at 08:57
7

This is a simple solution for the Delphi version with generics:

TUniqueList<T> = class(TList<T>)
public
  function Add(const Value: T): Integer;
end;

{ TUniqueList<T> }

function TUniqueList<T>.Add(const Value: T): Integer;
begin
  if not Contains(Value) then
    Result := inherited Add(Value);
end;

And if performance with lots of integers is important then you can keep the list sorted and use the binary serch

6

Delphi containers class in the "standard" VCL library are poor. This is a long standing issue only partially corrected in latest versions. If you are using Delphi >= 2009 you have generics class that can handle integer data types as well, before you have to write your own class, use TList in a non standard way, or use a third party library. If you have to store numbers, if they are at most 32 bit long you can store them in a TList, casting them to and from pointers. You have to override the Add() method to ensure uniqueness. You could also use TBits and set to true the corresponding "slot". Otherwise you need to use third party libraries like the JCL (free) or DIContainers (commercial), for example.

  • 1
    i am sorry , buts is a "no NO" for me to cast pointers as number. if i am giving up the safety of working with strongly type language i might as well go Lisp. if i accidentally make a memory call with these numbers, the way back from that mess is soooo long that i don't even want to imagine it. – none Oct 12 '10 at 13:38
  • 2
    You would make memory calls with pointer of a list you know nothing about? You need more than just a strongly typed language it seems... He's not talking about mixing pointers and integers in the same list (that would be bad). – Ken Bourassa Oct 12 '10 at 14:48
  • 1
    true, however if you are tired enough then you would be suprized at the wonders people go to , to make your life a leaving hell for a day or two, just beacuse they didnt get enough sleep. "this is your brain before drugs, this your brains after bugs. do you want to try it?" or in a better way to say it "code your code as if a serial killer will review your code, and he knows where you live." – none Oct 12 '10 at 15:08
  • "if i am giving up the safety of working with strongly type language i might as well go Lisp" <-- Fail. (Common) Lisp is _more_ strongly typed than Delphi. It's trivial to subvert Delphi's type system, as it is in any type system with an untyped pointer (Pointer, or void *). – Frank Shearar Oct 12 '10 at 15:52
  • 3
    I see nothing wrong with implementing an integer list container like so: TMyList = class(TObject) private List: TList; end; and ensuring type safety with a suitable add/get. Exposing the internal list would be silly though! – Frank Shearar Oct 12 '10 at 15:53
4

You can use a TList to store a set of integers. It is supposed to store Pointers, but since Pointers are just integers it works perfectly when storing Integers.

Toby Allen
  • 10,997
  • 11
  • 73
  • 124
2

Delphi has unit mxarrays (Decision Cube), there is a class TIntArray, set it's property Duplicates to dupIgnore. It's also can sort values. If you will use it, see Quality Central Report #:2703 to correct the bug in this unit.

Schnider
  • 93
  • 1
  • 5
1

Personally, i strongly recommend start using DeCAL for storing data. It has DMap container which can handle almost any data type, is self optimized because it uses internal Red-Black tree and it won't allow you to add duplicates (if you need to insert duplicates, you can use DMultiMap). Another great thing with DMap is that finding element in the list is very fast (much faster than in TStringList). Working with DeCal is a bit different than with other Delphi libraries but once you get comfortable with it, you won't use any StringList in your code.

Edit: older version of DeCAL is on SourceForge, but here you can find great pdf manual.

Linas
  • 5,485
  • 1
  • 25
  • 35
0

Yes, there is, it's called TDictionary

radu122
  • 2,865
  • 24
  • 24