Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2013-06

Foreach?

16 messages · 6 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Timothy Groves

So I've got this code:

     frmMain.btnMacro1.Caption := MacroList [0].Name;
     frmMain.btnMacro2.Caption := MacroList [1].Name;
     frmMain.btnMacro3.Caption := MacroList [2].Name;
     frmMain.btnMacro4.Caption := MacroList [3].Name;
     frmMain.btnMacro5.Caption := MacroList [4].Name;
     frmMain.btnMacro6.Caption := MacroList [5].Name;
     frmMain.btnMacro7.Caption := MacroList [6].Name;
     frmMain.btnMacro8.Caption := MacroList [7].Name;
     frmMain.btnMacro9.Caption := MacroList [8].Name;
     frmMain.btnMacro10.Caption := MacroList [9].Name;

There's gotta be some kind of construction that would let me foreach this. Any suggestions?

Reply by email

Sven Barth
to Timothy Groves
Timothy Groves wrote 15 lines
So I've got this code: frmMain.btnMacro1.Caption := MacroList [0].Name; frmMain.btnMacro2.Caption := MacroList [1].Name; frmMain.btnMacro3.Caption := MacroList [2].Name; frmMain.btnMacro4.Caption := MacroList [3].Name; frmMain.btnMacro5.Caption := MacroList [4].Name; frmMain.btnMacro6.Caption := MacroList [5].Name; frmMain.btnMacro7.Caption := MacroList [6].Name; frmMain.btnMacro8.Caption := MacroList [7].Name; frmMain.btnMacro9.Caption := MacroList [8].Name; frmMain.btnMacro10.Caption := MacroList [9].Name; There's gotta be some kind of construction that would let me foreach this. Any suggestions?

Untested code, but somehow like this it should work (maybe "ControlCount" and "Controls" are named differently...):

=== code begin ===

c := 0;
for i := 0 to frmMain.ControlCount - 1 do
   if (frmMain.Controls[i] is TButton) and (Pos('btnMacro',
frmMain.Controls[i].Name) = 1) then begin
     frmMain.Controls[i].Caption := MacroList[c].Name;
     Inc(c);
   end;

=== code end ===

Regards,
Sven

Reply by email

Timothy Groves
to Sven Barth
Sven Barth wrote 8 lines
c := 0; for i := 0 to frmMain.ControlCount - 1 do if (frmMain.Controls[i] is TButton) and (Pos('btnMacro', frmMain.Controls[i].Name) = 1) then begin frmMain.Controls[i].Caption := MacroList[c].Name; Inc(c); end;

I can see how this might work. Unfortunately, it does not, and attempts to debug it crash the debugger...

Reply by email

Martin
to Timothy Groves
Timothy Groves wrote 11 lines
On 13-06-08 03:49 AM, Sven Barth wrote: > > c := 0; > for i := 0 to frmMain.ControlCount - 1 do > if (frmMain.Controls[i] is TButton) and (Pos('btnMacro', > frmMain.Controls[i].Name) = 1) then begin > frmMain.Controls[i].Caption := MacroList[c].Name; > Inc(c); > end; I can see how this might work. Unfortunately, it does not, and attempts to debug it crash the debugger...

There are other controls in that list (other than btnMacroX)

You must ensure, that "inc(i)" is only called if it is a btnMacro. Otherwise it grows to big....

Also the order is not guaranteed. So inc(i) does not work. Better to parse the number, from the name using
intToStr(copy(frmMain.Controls[i].Name, 8,999))
assuming there never is anything after the number.

--------------
As for the debugger crash, could you reproduce it And produce a log?

http://wiki.lazarus.freepascal.org/GDB_Debugger_Tips#Log_info_for_debug_session

Reply by email

Sven Barth
to Martin
Martin wrote 18 lines
On 08/06/2013 08:56, Timothy Groves wrote: > On 13-06-08 03:49 AM, Sven Barth wrote: >> >> c := 0; >> for i := 0 to frmMain.ControlCount - 1 do >> if (frmMain.Controls[i] is TButton) and (Pos('btnMacro', >> frmMain.Controls[i].Name) = 1) then begin >> frmMain.Controls[i].Caption := MacroList[c].Name; >> Inc(c); >> end; > I can see how this might work. Unfortunately, it does not, and > attempts to debug it crash the debugger... There are other controls in that list (other than btnMacroX) You must ensure, that "inc(i)" is only called if it is a btnMacro. Otherwise it grows to big....

The "Inc(c)" is inside the if-branch that checks for the control's name.

Also the order is not guaranteed. So inc(i) does not work. Better to parse the number, from the name using intToStr(copy(frmMain.Controls[i].Name, 8,999)) assuming there never is anything after the number.

That would indeed be a better idea...

Regards,
Sven

Reply by email

Sven Barth
to Antônio
Ant?nio wrote
for i := 0 to 9 do TButton(Form1.FindComponent('btnMacro' + IntToStr(i + 1))).Caption := Macrolist[i].Name;

Also an interesting solution though that might have the problem that you basically do two loops (depending on the implementation of FindComponent). So doing that once on startup should be ok, otherwise I wouldn't use it...

Regards,
Sven

Reply by email

Antônio
to Antônio

For a single loop, maybe this, if was not so complicated:

for i := 0 to Form1.ComponentCount - 1 do
    if Pos('btnMacro', Form1.Components[i].Name) = 1 then
      TButton(Form1.Components[i]).Name :=
MacroList[StrToInt(Copy(Form1.Components[i].Name, 9, 2))].Name;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20130608/30c8bbe0/attachment.html>

Reply by email

Sven Barth
to Antônio: That is not so bad, since what FindComponent loop does is the same as Barth done with his…
Ant?nio wrote
That is not so bad, since what FindComponent loop does is the same as Barth done with his loop, matching the name of the component.

Thinking about it a bit more in the end both approaches should be O(n):

In my approach you have the loop over all Controls and then the "loop" when doing the Pos. The latter can be seen as neglectable and by using Copy + "=" this can be reduced to a constant time. So it's O(n).

Your approach first has the constant loop from 1 to 10, then the FindComponent loop which is O(n) and the way of finding the correct component name which can be considered constant again.

So only difference might be execution speed and that would need to be tested especially with a random distribution of the Button controls among the Controls array.

Sidenote: I prefer being called by my first name on the mailing list.

Regards,
Sven

Reply by email

Flávio Etrusco
to Sven Barth
Sven Barth wrote 19 lines
On 08.06.2013 19:52, Ant?nio wrote: > > That is not so bad, since what FindComponent loop does is the same as > Barth done with his loop, matching the name of the component. Thinking about it a bit more in the end both approaches should be O(n): In my approach you have the loop over all Controls and then the "loop" when doing the Pos. The latter can be seen as neglectable and by using Copy + "=" this can be reduced to a constant time. So it's O(n). Your approach first has the constant loop from 1 to 10, then the FindComponent loop which is O(n) and the way of finding the correct component name which can be considered constant again. So only difference might be execution speed and that would need to be tested especially with a random distribution of the Button controls among the Controls array.

If you use AnsiStartWith (or similar) your (single loop) version will be really O(n) (for the number of Controls). And the FindComponent approach then be rightfully considered O(m^p) (no of buttons, no of Components - not Controls).
There's no arguing FindComponent (or GetFieldAddress if the buttons are published/streamed) is more readable, tough.

Show quoted text 5 lines
Sidenote: I prefer being called by my first name on the mailing list. Regards, Sven

Best regards,
Fl?vio

Reply by email