FindMapElement no case

Just starting out? Need help? Post your questions and find answers here.
wayne-c
Enthusiast
Enthusiast
Posts: 337
Joined: Tue Jun 08, 2004 10:29 am
Location: Zurich, Switzerland

FindMapElement no case

Post 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"...
As you walk on by, Will you call my name? Or will you walk away?
wombats
Enthusiast
Enthusiast
Posts: 716
Joined: Thu Dec 29, 2011 5:03 pm

Re: FindMapElement no case

Post by wombats »

Before using the XML document, could you loop through it and convert everything to the same case?
wayne-c
Enthusiast
Enthusiast
Posts: 337
Joined: Tue Jun 08, 2004 10:29 am
Location: Zurich, Switzerland

Re: FindMapElement no case

Post 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?
As you walk on by, Will you call my name? Or will you walk away?
User avatar
Derren
Enthusiast
Enthusiast
Posts: 316
Joined: Sat Jul 23, 2011 1:13 am
Location: Germany

Re: FindMapElement no case

Post 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.
wayne-c
Enthusiast
Enthusiast
Posts: 337
Joined: Tue Jun 08, 2004 10:29 am
Location: Zurich, Switzerland

Re: FindMapElement no case

Post 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)
As you walk on by, Will you call my name? Or will you walk away?
wayne-c
Enthusiast
Enthusiast
Posts: 337
Joined: Tue Jun 08, 2004 10:29 am
Location: Zurich, Switzerland

Re: FindMapElement no case

Post 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
As you walk on by, Will you call my name? Or will you walk away?
Marc56us
Addict
Addict
Posts: 1600
Joined: Sat Feb 08, 2014 3:26 pm

Re: FindMapElement no case

Post 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:
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: FindMapElement no case

Post 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.
Last edited by srod on Fri Jan 25, 2019 11:09 am, edited 1 time in total.
I may look like a mule, but I'm not a complete ass.
User avatar
Derren
Enthusiast
Enthusiast
Posts: 316
Joined: Sat Jul 23, 2011 1:13 am
Location: Germany

Re: FindMapElement no case

Post 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?
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: FindMapElement no case

Post by srod »

I'm guessing the map is one of the structure fields.
I may look like a mule, but I'm not a complete ass.
dempdeezzpp
User
User
Posts: 11
Joined: Wed Feb 03, 2021 12:04 am

Re: FindMapElement no case

Post 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
infratec
Always Here
Always Here
Posts: 7583
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: FindMapElement no case

Post 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
dempdeezzpp
User
User
Posts: 11
Joined: Wed Feb 03, 2021 12:04 am

Re: FindMapElement no case

Post 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
User avatar
Josh
Addict
Addict
Posts: 1183
Joined: Sat Feb 13, 2010 3:45 pm

Re: FindMapElement no case

Post 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
sorry for my bad english
User avatar
HeX0R
Addict
Addict
Posts: 1189
Joined: Mon Sep 20, 2004 7:12 am
Location: Hell

Re: FindMapElement no case

Post by HeX0R »

I'm pretty sure he solved the issue within the past 2 years :mrgreen:
Post Reply