Page 1 of 1
[Solved] ForEach loop with Maps
Posted: Sun Aug 04, 2024 7:25 am
by BarryG
I'm still getting used to maps, so the code below doesn't make sense to me. If I set the value of "icon" to 1, then ForEach/Next goes into an endless loop, but NOT if I set "icon" to 2 or 3. Why? What's so special about "1" that it doesn't stop the loop?
Reason for asking: I have a Map of all icons loaded by my app, but sometimes I'll load an icon on demand that ISN'T in the map (like "three=" below). So I need a way to work out if any given icon is in the map or not. I thought ForEach/Next could do this, but with an endless loop I can't use it.
Code: Select all
NewMap IconMap()
IconMap("1")=1
IconMap("2")=2
three=LoadIcon_(0,#IDI_APPLICATION) ; Purposely not in the map.
icon=1 ; Endless loop, but NOT if set to 2 or 3. Why?
ForEach IconMap()
Debug IconMap(Str(icon))
Next
Re: ForEach loop with Maps
Posted: Sun Aug 04, 2024 7:37 am
by DarkDragon
By accessing a different key you change the current element. Store the old current element and restore it afterwards with PushMapPosition(Map()) and PopMapPosition(Map()):
Code: Select all
ForEach IconMap()
PushMapPosition(IconMap())
Debug IconMap(Str(icon))
PopMapPosition(IconMap())
Next
However checking whether a key is inside a map is done via FindMapElement(Map(), Key$), you don't iterate all elements.
Re: ForEach loop with Maps
Posted: Sun Aug 04, 2024 7:57 am
by BarryG
Thanks, that helped me work out my problem!

This was my goal:
Code: Select all
NewMap IconMap()
IconMap("1")=1
IconMap("2")=2
three=LoadIcon_(0,#IDI_APPLICATION) ; Purposely not in the map.
Debug FindMapElement(IconMap(),Str(1)) ; Non-zero means in the map.
Debug FindMapElement(IconMap(),Str(2)) ; Non-zero means in the map.
Debug FindMapElement(IconMap(),Str(three)) ; 0 means NOT in the map.
Re: ForEach loop with Maps
Posted: Sun Aug 04, 2024 9:16 am
by Bisonte
Code: Select all
Procedure.i IsInIconMap(Number)
Protected Result = #False
PushMapPosition(IconMap())
If FindMapElement(IconMap(), Str(Number))
Result = #True
EndIf
PopMapPosition(IconMap())
ProcedureReturn Result
EndProcedure
Where IconMap() is global....
else
Code: Select all
Procedure.i IsInIconMap(Map IconMap(), Number)
Re: [Solved] ForEach loop with Maps
Posted: Sun Aug 04, 2024 9:34 am
by BarryG
Thank you, Bisonte.

Re: [Solved] ForEach loop with Maps
Posted: Sun Aug 04, 2024 12:30 pm
by boddhi
Hello,
For further information (just in case),
We need to be careful, as some operations can implicitly create an element without an assignment:
Code: Select all
NewMap IconMap()
IconMap("1")=1
IconMap("2")=2
Debug FindMapElement(IconMap(),"3")
If IconMap("3"):EndIf
Debug FindMapElement(IconMap(),"3")
ALWAYS use FindMapElement() to check if a key really exists.
Re: [Solved] ForEach loop with Maps
Posted: Tue Aug 06, 2024 9:08 am
by Mesa
It's a bug, you should inform fred on the appropriate forum.
M.
Re: [Solved] ForEach loop with Maps
Posted: Tue Aug 06, 2024 10:17 am
by mk-soft
Mesa wrote: Tue Aug 06, 2024 9:08 am
It's a bug, you should inform fred on the appropriate forum.
M.
The behaviour was changed in this point because it led to other problems in other points.
FindMapElement must be used explicitly.
Re: [Solved] ForEach loop with Maps
Posted: Tue Aug 06, 2024 11:17 am
by boddhi
mk-soft wrote:
FindMapElement must be used explicitly.
As it's not explicitly explained in the (French, anyway) documentation, knowing this would have saved me, some time ago, the trouble of trying to understand why one of my codes wasn't working properly!

Re: [Solved] ForEach loop with Maps
Posted: Tue Aug 06, 2024 10:12 pm
by AZJIO
I always use AddMapElement() and have never encountered a problem yet. I think you are trying to shorten the entry using simplified assignment.
You list the map elements
Code: Select all
ForEach IconMap()
Debug IconMap()
Next
When you set IconMap("1") in a loop, you probably reset the current position of the element listing, you have "1" every time, and always strive for "2".
Code: Select all
Dim Arr(2)
Arr(0) = 1
Arr(1) = 2
Arr(2) = 3
For i = 0 To 2
Debug Arr(i)
Next
; Now guess why you always have the same number infinitely
For i = 0 To 2
i=1
Debug Arr(i)
Next
Code: Select all
NewList IconList()
AddElement(IconList())
IconList() = 1
AddElement(IconList())
IconList() = 2
ForEach IconList()
Debug IconList()
Next
; Now guess why you always have the same number infinitely
ForEach IconList()
SelectElement(IconList() , 0)
Debug IconList()
Next