Page 1 of 2

FindMapElement no case

Posted: Thu Jan 24, 2019 4:11 pm
by wayne-c
I need a case insensitive version of the FindMapElement() function. Any ideas?
Thank you in advance!

Background: I parse XML documents into maps where the end-user may write for the element keys either key="START" or key="Start" or key="start"...

Re: FindMapElement no case

Posted: Thu Jan 24, 2019 4:16 pm
by wombats
Before using the XML document, could you loop through it and convert everything to the same case?

Re: FindMapElement no case

Posted: Thu Jan 24, 2019 4:20 pm
by wayne-c
Well yes I might loop through the maps AFTER parsing and change the case of the key of all the nodes I need manually, but how can I do that without removing and adding all elements to the map? As far as I know there is no way of UPDATING a map's key?

Re: FindMapElement no case

Posted: Thu Jan 24, 2019 4:22 pm
by Derren
When parsing the document, already go for an all lower or upper case map key.
When the user enters his key, just convert it. No need to loop though the whole map after the fact.

Re: FindMapElement no case

Posted: Thu Jan 24, 2019 4:25 pm
by wayne-c
Derren wrote:When parsing the document, already go for an all lower or upper case map key.
When the user enters his key, just convert it. No need to loop though the whole map after the fact.
Not possible, I use ExtractXMLStructure():

Code: Select all

ExtractXMLStructure(MainNode, *Module, ModuleStruct, #PB_XML_NoCase)

Re: FindMapElement no case

Posted: Thu Jan 24, 2019 4:32 pm
by wayne-c
This is how I do it for the moment; however there must for sure be another FASTER method instead of removing/re-appending the map elements!

Code: Select all

ForEach *Module\Views()
	Protected CurrentKey$ = MapKey(*Module\Views())
	Protected UpperKey$ = UCase(CurrentKey$)
	If UpperKey$ <> CurrentKey$
		AddMapElement(*Module\Views(), UpperKey$)
		CopyStructure(*Module\Views(CurrentKey$), *Module\Views(UpperKey$), ModuleViewStruct)
		DeleteMapElement(*Module\Views(), CurrentKey$)
	EndIf
Next

Re: FindMapElement no case

Posted: Thu Jan 24, 2019 4:36 pm
by Marc56us
:idea: A solution with with NextMapElement()
(I don't know if it's faster or slower than FindMapElement())

Code: Select all

NewMap Key.s()

Key("START") = "All Upcase"
Key("Start") = "First Upcase"
Key("start") = "No Upcase"
Key("Hello") = "Hello World"
Key("World") = "HELLO WORLD"

While NextMapElement(Key())
    If UCase(MapKey(Key())) = "START"
        Debug MapKey(Key())
    EndIf
Wend

Code: Select all

Start
START
start
:?: :wink:

Re: FindMapElement no case

Posted: Thu Jan 24, 2019 7:19 pm
by srod
Who is responsible for creating the XML files? If it is a piece of software of yours then, well, easy job to create the relevant XML nodes with lowercase map keys etc.

Otherwise, you could simply parse the XML map node without using ExtractXMLStructure() and instead parse the individual elements and create the map as you proceed. Might be the quickest way.

Re: FindMapElement no case

Posted: Fri Jan 25, 2019 10:09 am
by Derren
wayne-c wrote:
Derren wrote:When parsing the document, already go for an all lower or upper case map key.
When the user enters his key, just convert it. No need to loop though the whole map after the fact.
Not possible, I use ExtractXMLStructure():

Code: Select all

ExtractXMLStructure(MainNode, *Module, ModuleStruct, #PB_XML_NoCase)
I don't understand. This code just fills up a structured variable. It doesn't have anything to do with maps. How do you determine the Mapkey?

Re: FindMapElement no case

Posted: Fri Jan 25, 2019 11:08 am
by srod
I'm guessing the map is one of the structure fields.

Re: FindMapElement no case

Posted: Thu Mar 04, 2021 1:44 pm
by dempdeezzpp
wayne-c wrote:This is how I do it for the moment; however there must for sure be another FASTER method instead of removing/re-appending the map elements!

Code: Select all

ForEach *Module\Views()
	Protected CurrentKey$ = MapKey(*Module\Views())
	Protected UpperKey$ = UCase(CurrentKey$)
	If UpperKey$ <> CurrentKey$
		AddMapElement(*Module\Views(), UpperKey$)
		CopyStructure(*Module\Views(CurrentKey$), *Module\Views(UpperKey$), ModuleViewStruct)
		DeleteMapElement(*Module\Views(), CurrentKey$)
	EndIf
Next
Hi! How can you get Mapsize this code:

DeclareModule Item

#Version = 19042800

Enumeration 1
#FullPatch
#FolderPatch
#FolderFiles
EndEnumeration

Declare SetData(GId.i, Index.i, Value.s)
Declare.s GetData(GId.i, Index.i)
Declare RemoveData(GId.i)
Declare FreeData()

EndDeclareModule


Module Item

Structure Item_Structure ;{ IDEx()\...
Map Patches.s()
EndStructure
Global NewMap IDEx.Item_Structure();}

Procedure SetData(GId.i, Index.i, Value.s)
IDEx(Str(GId))\Patches(Str(Index)) = Value
EndProcedure

Procedure.s GetData(GId.i, Index.i)
ProcedureReturn IDEx(Str(GId))\Patches(Str(Index))
EndProcedure

Procedure RemoveData(GId.i)
If FindMapElement(IDEx(), Str(GId))
DeleteMapElement(IDEx())
EndIf
EndProcedure

Procedure FreeData()
ClearMap(IDEx())
EndProcedure

EndModule


CompilerIf #PB_Compiler_IsMainFile

For i=1 To 25
Item::SetData(Item::#FullPatch, i, "FullPatch " + Str(i))
Next i

Debug Item::GetData(Item::#FullPatch, 6)

CompilerEndIf

Re: FindMapElement no case

Posted: Thu Mar 04, 2021 3:43 pm
by infratec
Your question has nothing to do with this thread.
Open a new one next time.

Code: Select all

DeclareModule Item
  
  #Version = 19042800
  
  Enumeration 1
    #FullPatch
    #FolderPatch
    #FolderFiles
  EndEnumeration
  
  Declare SetData(GId.i, Index.i, Value.s)
  Declare.s GetData(GId.i, Index.i)
  Declare RemoveData(GId.i)
  Declare FreeData()
  Declare.i GetElements(GId.i)
  
EndDeclareModule


Module Item
  
  Structure Item_Structure ;{ IDEx()\...
    Map Patches.s()
  EndStructure
  Global NewMap IDEx.Item_Structure();}
  
  Procedure SetData(GId.i, Index.i, Value.s)
    IDEx(Str(GId))\Patches(Str(Index)) = Value
  EndProcedure
  
  Procedure.s GetData(GId.i, Index.i)
    ProcedureReturn IDEx(Str(GId))\Patches(Str(Index))
  EndProcedure
  
  Procedure RemoveData(GId.i)
    If FindMapElement(IDEx(), Str(GId))
      DeleteMapElement(IDEx())
    EndIf
  EndProcedure
  
  Procedure FreeData()
    ClearMap(IDEx())
  EndProcedure
  
  Procedure.i GetElements(GId.i)
    ProcedureReturn MapSize(IDEx(Str(GId))\Patches())
  EndProcedure
  
EndModule


CompilerIf #PB_Compiler_IsMainFile
  
  For i=1 To 25
    Item::SetData(Item::#FullPatch, i, "FullPatch " + Str(i))
  Next i
  
  Debug Item::GetData(Item::#FullPatch, 6)
  
  Debug Item::GetElements(Item::#FullPatch)
  
CompilerEndIf

Re: FindMapElement no case

Posted: Thu Mar 04, 2021 7:31 pm
by dempdeezzpp
infratec wrote:Your question has nothing to do with this thread.
Open a new one next time.

Code: Select all

DeclareModule Item
  
  #Version = 19042800
  
  Enumeration 1
    #FullPatch
    #FolderPatch
    #FolderFiles
  EndEnumeration
  
  Declare SetData(GId.i, Index.i, Value.s)
  Declare.s GetData(GId.i, Index.i)
  Declare RemoveData(GId.i)
  Declare FreeData()
  Declare.i GetElements(GId.i)
  
EndDeclareModule


Module Item
  
  Structure Item_Structure ;{ IDEx()\...
    Map Patches.s()
  EndStructure
  Global NewMap IDEx.Item_Structure();}
  
  Procedure SetData(GId.i, Index.i, Value.s)
    IDEx(Str(GId))\Patches(Str(Index)) = Value
  EndProcedure
  
  Procedure.s GetData(GId.i, Index.i)
    ProcedureReturn IDEx(Str(GId))\Patches(Str(Index))
  EndProcedure
  
  Procedure RemoveData(GId.i)
    If FindMapElement(IDEx(), Str(GId))
      DeleteMapElement(IDEx())
    EndIf
  EndProcedure
  
  Procedure FreeData()
    ClearMap(IDEx())
  EndProcedure
  
  Procedure.i GetElements(GId.i)
    ProcedureReturn MapSize(IDEx(Str(GId))\Patches())
  EndProcedure
  
EndModule


CompilerIf #PB_Compiler_IsMainFile
  
  For i=1 To 25
    Item::SetData(Item::#FullPatch, i, "FullPatch " + Str(i))
  Next i
  
  Debug Item::GetData(Item::#FullPatch, 6)
  
  Debug Item::GetElements(Item::#FullPatch)
  
CompilerEndIf

thanks, I'll take into account

Re: FindMapElement no case

Posted: Thu Mar 04, 2021 10:35 pm
by Josh
@wayne-c

I don't understand the problem either, why you can't create the map key in uppercase right away, but alternatively you can do the following:

Write your data to a list and when it's done, run through the list and create parallel a pointermap pointing to the list.

Code: Select all

Structure MYSTRUC
  Name$
  x.i
EndStructure

NewList MyList.MYSTRUC()
NewMap *MyMap.MYSTRUC()


AddElement (MyList()) : MyList()\Name$ = "Name1" : MyList()\x = 11
AddElement (MyList()) : MyList()\Name$ = "Name2" : MyList()\x = 22
AddElement (MyList()) : MyList()\Name$ = "Name3" : MyList()\x = 33
AddElement (MyList()) : MyList()\Name$ = "Name4" : MyList()\x = 44
AddElement (MyList()) : MyList()\Name$ = "Name5" : MyList()\x = 55

ForEach MyList()
  AddMapElement (*MyMap(), UCase (MyList()\Name$))
  *MyMap() = @MyList()
Next


ForEach *MyMap()
  Debug MapKey (*MyMap()) + " - " + *MyMap()\Name$ + " - " + *MyMap()\x
Next

Re: FindMapElement no case

Posted: Thu Mar 04, 2021 11:30 pm
by HeX0R
I'm pretty sure he solved the issue within the past 2 years :mrgreen: