[Solved] ForEach loop with Maps

Just starting out? Need help? Post your questions and find answers here.
BarryG
Addict
Addict
Posts: 4219
Joined: Thu Apr 18, 2019 8:17 am

[Solved] ForEach loop with Maps

Post 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
Last edited by BarryG on Sun Aug 04, 2024 9:34 am, edited 1 time in total.
DarkDragon
Addict
Addict
Posts: 2347
Joined: Mon Jun 02, 2003 9:16 am
Location: Germany
Contact:

Re: ForEach loop with Maps

Post 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.
bye,
Daniel
BarryG
Addict
Addict
Posts: 4219
Joined: Thu Apr 18, 2019 8:17 am

Re: ForEach loop with Maps

Post 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.
User avatar
Bisonte
Addict
Addict
Posts: 1320
Joined: Tue Oct 09, 2007 2:15 am

Re: ForEach loop with Maps

Post 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)
PureBasic 6.21 (Windows x64) | Windows 11 Pro | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
English is not my native language... (I often use DeepL.)
BarryG
Addict
Addict
Posts: 4219
Joined: Thu Apr 18, 2019 8:17 am

Re: [Solved] ForEach loop with Maps

Post by BarryG »

Thank you, Bisonte. :)
boddhi
Enthusiast
Enthusiast
Posts: 524
Joined: Mon Nov 15, 2010 9:53 pm

Re: [Solved] ForEach loop with Maps

Post 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.
If my English syntax and lexicon are incorrect, please bear with Google translate and DeepL. They rarely agree with each other!
Except on this sentence...
Mesa
Enthusiast
Enthusiast
Posts: 447
Joined: Fri Feb 24, 2012 10:19 am

Re: [Solved] ForEach loop with Maps

Post by Mesa »

It's a bug, you should inform fred on the appropriate forum.

M.
User avatar
mk-soft
Always Here
Always Here
Posts: 6320
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: [Solved] ForEach loop with Maps

Post 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.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
boddhi
Enthusiast
Enthusiast
Posts: 524
Joined: Mon Nov 15, 2010 9:53 pm

Re: [Solved] ForEach loop with Maps

Post 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! :mrgreen:
If my English syntax and lexicon are incorrect, please bear with Google translate and DeepL. They rarely agree with each other!
Except on this sentence...
AZJIO
Addict
Addict
Posts: 2225
Joined: Sun May 14, 2017 1:48 am

Re: [Solved] ForEach loop with Maps

Post 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
Post Reply