17

I want to iterate through a set of specific values. Simple example below

program Project1;
{$APPTYPE CONSOLE}

var
  a, b: word;
  wait: string;

begin
  a := 0;
  for b in [1,5,10,20] do
  begin
    a := a + 1;
    writeln('Iteration = ', a, ',   value = ', b);
  end;

  read(wait); 

end.

The sample code here does what I expect and produces the following

Iteration = 1, value = 1

Iteration = 2, value = 5

Iteration = 3, value = 10

Iteration = 4, value = 20

Now if I change the order of the set

  for b in [20,10,5,1] do

The output is the same as the original, that is the order of the values is not preserved.

What is the best way to implement this?

HMcG
  • 2,062
  • 4
  • 24
  • 36

3 Answers3

24

Sets are not ordered containers. You cannot change the order of a set's contents. A for-in loop always iterates through sets in numerical order.

If you need an ordered list of numbers, then you can use an array or TList<Integer>.

var
  numbers: array of Word;
begin
  SetLength(numbers, 4);
  numbers[0] := 20;
  numbers[1] := 10;
  numbers[2] := 5;
  numbers[3] := 1;
  for b in numbers do begin
    Inc(a);
    Writeln('Iteration = ', a, ',   value = ', b);
  end;
end.
Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
  • 18
    e.g. `for b in TIntegerDynArray.Create(20,10,5,1) do` – David Heffernan Feb 09 '11 at 20:41
  • Thanks for the answer. Is there any less long-winded way to create the ordered array values? And the comment above answers that too. Sometimes StackOverflow is just too quick :-) – HMcG Feb 09 '11 at 20:45
  • The dynamic-array-constructor syntax that David demonstrates is newer than the for-in loop. There are some Delphi versions that can use the latter, but not the former, and if you're using one of those, then there's not much you can do. You could perhaps write your own function that converts an open array into a dynamic array. – Rob Kennedy Feb 09 '11 at 20:53
  • @David Hefferman - thanks, thats a very nice solution, and also overcomes the limits on a set (bytes only it seems, even in DXE). – HMcG Feb 09 '11 at 20:57
  • @Rob: It goes back at least as far as D2007, though. It wasn't in D7, I don't believe. (Just to give people an idea of the approximate time it appeared; not correcting your post or comment.) – Ken White Feb 09 '11 at 20:58
  • @Rob Functions turning open arrays into dynamic arrays are often necessary because the dynamic array constructor syntax doesn't admit open arrays which rather negates its utility in my view. I have a big collection of functions that do this job, oh for templates or even generics that worked (I'm talking about you D2010!) – David Heffernan Feb 09 '11 at 21:54
  • Great answer! Great comment @DavidHeffernan! I used a custom array of enums: `TCustomArray = TArray; ... for b in TCustomArray.Create(customly sorted enums) do ...`. Maybe other beginners will find this useful, that it doesn't only apply to integers or already default arrays. – Mike Torrettinni May 28 '16 at 20:19
13

You can declare a constant array instead of a constant set.

program Project1;
{$APPTYPE CONSOLE}

var
  a, b: word;
  wait: string;
const
  values: array[0..3] of word = (20,5,10,1);

begin
  a := 0;
  for b in values do
  begin
    a := a + 1;
    writeln('Iteration = ', a, ',   value = ', b);
  end;

  read(wait);

end.
RichardTheKiwi
  • 105,798
  • 26
  • 196
  • 262
  • Another nice implementation, and this one does not rely on any other units. Thanks. – HMcG Feb 09 '11 at 21:13
7

In math, a set have no particular order.

In pascal, a set is a bitmap in memory representation of the elements present in the set (within a universe of possible elements defined by the base type).

There's no way you can "change" the order of a set, because it is, by definition, meaningless for it.

As the in memory representation by pascal, the set is always iterated "in order".

jachguate
  • 16,976
  • 3
  • 57
  • 98
  • 1
    thanks for the explanation. I must admit I had not realized that it is, as you say , a mapped representation of the values - that also explains why duplicate values have no effect - that value is already represented. – HMcG Feb 09 '11 at 21:07