I use Map() and don't want it to auto sort.
How to stop auto sort when using Map() in v2 ?
Stop auto sort in Map ? Topic is solved
Re: Stop auto sort in Map ? Topic is solved
what kind of usage case or implementation do you need? If you want to record elements in a specific order, then an array is your best bet.
You can put ["my key", other_value] as a single element in an array, and you could make a func to look up your other_value by iterating through the array.
This lookup code works well, but you'll have to decide how to populate the array.
You can put ["my key", other_value] as a single element in an array, and you could make a func to look up your other_value by iterating through the array.
Code: Select all
arr := [ ["key1", "value1"]
,["key2", "value2"] ]
msgbox lookup(arr, "key2")
lookup(arr, str) {
for i, obj in arr
if obj[1] = str
return obj[2]
return ""
}
« AHK Portable Installer » | « CallTipsForAll » | « TheArkive AHK v1 Scripts » | « TheArkive AHK v2 Scrpts » | « TheArkive on GitHub »
Re: Stop auto sort in Map ?
I'm so stupid for not thinking this , thanks TheArkive !
Re: Stop auto sort in Map ?
For what it's worth, I didn't think it was a silly question
I'm sure other people will find this info helpful too as they learn AHK v2.
Glad it worked for ya.
I'm sure other people will find this info helpful too as they learn AHK v2.
Glad it worked for ya.
« AHK Portable Installer » | « CallTipsForAll » | « TheArkive AHK v1 Scripts » | « TheArkive AHK v2 Scrpts » | « TheArkive on GitHub »
Re: Stop auto sort in Map ?
by not using Map. u can use a ComObject('Scripting.Dictionary') instead or write ur own Map that keeps track of the insertions, eg one with bad performance and memory footprint:
Code: Select all
#Requires AutoHotkey v2.0-beta.1
class OrderedMap extends Map
{
__New(KVPairs*) {
super.__New(KVPairs*)
KeyArray := []
keyCount := KVPairs.Length // 2
KeyArray.Length := keyCount
Loop keyCount
KeyArray[A_Index] := KVPairs[(A_Index << 1) - 1]
this.KeyArray := KeyArray
}
__Item[key] {
set {
if !this.Has(key)
this.KeyArray.Push(key)
return super[key] := value
}
}
Clear() {
super.Clear()
this.KeyArray := []
}
Clone() {
Other := super.Clone()
Other.KeyArray := this.KeyArray.Clone()
return Other
}
Delete(key) {
try
{
RemovedValue := super.Delete(key)
CaseSense := this.CaseSense
for i, Element in this.KeyArray
{
areSame := (Element is String)
? !StrCompare(Element, key, CaseSense)
: (Element = key)
if areSame
{
this.KeyArray.RemoveAt(i)
break
}
}
return RemovedValue
}
catch KeyError as Err
throw KeyError(Err.Message, -1, Err.Extra)
}
Set(KVPairs*) {
if (KVPairs.Length & 1)
throw ValueError('Invalid number of parameters.', -1)
KeyArray := this.KeyArray
keyCount := KVPairs.Length // 2
KeyArray.Capacity += keyCount
Loop keyCount
{
key := KVPairs[(A_Index << 1) - 1]
if !this.Has(key)
KeyArray.Push(key)
}
super.Set(KVPairs*)
return this
}
__Enum(*) {
keyEnum := this.KeyArray.__Enum(1)
keyValEnum(&key := unset, &val := unset) {
if keyEnum(&key)
{
val := this[key]
return true
}
}
return keyValEnum
}
}
e: "fixed" to allow enumerating just the values, although eww
Last edited by swagfag on 08 Oct 2021, 19:31, edited 1 time in total.
Re: Stop auto sort in Map ?
@swagfag , I love your idea, and I think I might use it in my library too. I do have need for ordered map once in a while. I was wondering about your comment:
Without you spending any more time rewriting this, could you tell the general idea/description of what you'd do to improve performance and memory footprint? I had a couple of ideas, but I'm not even sure they would improve things, or are even possible:eg one with bad performance and memory footprint
- On the memory side, I was initially thinking maybe you could just track a VarRef to the key rather than the key itself, but I'm not sure you can get a VarRef to the key. Can you?
- On the performance side, I was trying to figure out what I'd do differently, but I couldn't think of much. Is there a particular part that you think could have better performance? Maybe deletion? I guess instead of keeping a side array of keys, you could intercept set/get and turn each value into an 2-field object containing both the intended value itself as well as a VarRef to the next key (or EOList object)?
Re: Stop auto sort in Map ?
idk, pick a different data structure better suited for the task - a Map smashed together with an Array full of duplicate keys doesnt seem like it(which is what this effectively is). but in any case u should benchmark first, if its needed. because it may turn out the dumb implementation backed by native code(Map/Array/Scripting.Dictionary) still beats out a cleverer ahk-code implementation. if ure hardcore, i guess u could write it as a DLL but thats opening a whole nother can of worms(and if the DllCall call overhead happens to be bad enough, might end up being slower regardless!)
u can, but that doesnt get u anywhere - the VarRefs still have to be stored somewhere• On the memory side, I was initially thinking maybe you could just track a VarRef to the key rather than the key itself, but I'm not sure you can get a VarRef to the key. Can you?
cant say anything. uve created a linked list basically. linear iteration through a chain of pointers all over the place doesnt sound like good performance to me, especially when its going to be done in ahk-code• intercept set/get and turn each value into an 2-field object containing both the intended value itself as well as a VarRef to the next key (or EOList object)?
Re: Stop auto sort in Map ?
Understood. Thanks for the additional insight.
I totally get your point. For small stuff, your original code seems perfectly great to me. For larger stuff, maybe the ComObject('Scripting.Dictionary') that you pointed out earlier (or even something else entirely) would be the way to go. When I get time to try a couple of options and profile them, I'll let you know what I find out. Thanks again!
I was thinking (that your original comment might have been) about long key names... I was thinking that a VarRef would only take an integer, where a string could take multiples of that, depending on key length... or maybe there's optimization of the strings behind the scenes? Also, maybe the VarRef object wrapper in ahk makes that approach too large to be worthwhile? In any event, I guess VarRefs aren't as similar as I thought to c pointers!VarRefs still have to be stored somewhere
Makes sense. That's what I was wondering. A linked list was kind of what I was going for, as I was assuming your original comment might have been about the need to traverse the entire array of keys to perform maintenance on it (especially left-side deletions). As above, I guess the VarRefs in ahk might be less efficient than the pointers one would use in c, not to mention the overhead of setting up the subarray/tuple for each new key's value.linear iteration through a chain of pointers all over the place doesnt sound like good performance to me, especially when its going to be done in ahk-code
I totally get your point. For small stuff, your original code seems perfectly great to me. For larger stuff, maybe the ComObject('Scripting.Dictionary') that you pointed out earlier (or even something else entirely) would be the way to go. When I get time to try a couple of options and profile them, I'll let you know what I find out. Thanks again!
Re: Stop auto sort in Map ?
Nice this works, except there's slight bug when you use OrderedMap() object in for loop without specifying key
Code: Select all
for , val in myOrderedMapArr {
}
Re: Stop auto sort in Map ?
simple. add unset and make the outputvar optional:
Code: Select all
...
keyValEnum(&key := unset, &val := unset) {
...
Re: Stop auto sort in Map ?
FYI there are a couple of issues that prevent the Map iterator from working in the later AHK versions, see the fixed version https://github.com/mmikeww/AHK-v2-script-converter/blob/master/lib/ClassOrderedMap.ahk
Re: Stop auto sort in Map ?
Code: Select all
MyMap := Map()
MyMap[1] := "Something"
MyMap[2] := "Something Else"
...
Who is online
Users browsing this forum: Daniel_San, Descolada, Google [Bot] and 33 guests