Page 1 of 1
[a108] N-dimensional map.
Posted: 30 Mar 2020, 09:39
by Helgef
To allow storing values at any
depth, eg,
myMap[1,2,3] := myValue.
See
github for source and example. Please report any problems.
Cheers.
Re: [a108] N-dimensional map.
Posted: 31 Jan 2023, 19:58
by FanaticGuru
Recently been learning v2 and this is very nice for getting a v1 associative array experience in v2.
Here is some examples that I played around with that seem to work well.
Code: Select all
MyMap := MapN()
MyMap["One","Two"] := "OneTwo"
MyMap["Three","Four", "Five"] := "ThreeFourFive"
MsgBox MyMap["One","Two"]
MsgBox MyMap["Three", "Four", "Five"]
MsgBox st_printArr(MyMap)
MyMap["One","Two","Three"] := "OneTwoThree"
MsgBox MyMap["One","Two","Three"]
MsgBox st_printArr(MyMap)
; String Things for testing
st_printArr(array, depth:=5, indentLevel:="")
{
for k,v in Array
{
list.= indentLevel "[" k "]"
if (IsObject(v) && depth>1)
list.="`n" st_printArr(v, depth-1, indentLevel . " ")
Else
list.=" => " v
list.="`n"
}
return rtrim(list)
}
; Helgef: An "n-dimensional" map.
class MapN extends map {
static __new()
=> this.prototype.class := this
__item[k1, p*] {
get => p.length ? super[k1][p*] : super[k1]
set {
if p.length && (!super.has(k1) || !(super[k1] is this.class))
super[k1] := (this.class)()
( p.length ) ? super[k1][p*] := value : super[k1] := value
}
}
}
Really like that it is super documented, but a slimmed down version of the function is at the end for easy inserting into other scripts. The utility to code size is impressive.
FG
Re: [a108] N-dimensional map.
Posted: 04 Feb 2023, 05:03
by Helgef
thanks for the feedback, glad you liked it.
Cheers.
Re: [a108] N-dimensional map.
Posted: 08 May 2023, 15:23
by FanaticGuru
Could you show me how to convert this so that it modifies the Map base object through prototype other than extending it with MapN?
FG
Re: [a108] N-dimensional map.
Posted: 08 May 2023, 19:25
by ntepa
FanaticGuru wrote: ↑08 May 2023, 15:23
Could you show me how to convert this so that it modifies the Map base object through prototype other than extending it with MapN?
Code: Select all
class MultiDimMap {
static __New() {
__set := Map.Prototype.GetOwnPropDesc("__Item").set
__get := Map.Prototype.GetOwnPropDesc("__Item").get
Map.Prototype.DefineProp("__Item", {
get:(self, k1, p*) => p.Length
? __get(self, k1)[p*]
: __get(self, k1),
set:(self, value, k1, p*) => (p.Length && (
!(Map.Prototype.Has)(self, k1)
|| !(__get(self, k1) is Map)
) && __set(self, (m:=Map(), m.CaseSense:=self.CaseSense, m), k1),
p.Length
? __get(self, k1)[p*] := value
: __set(self, value, k1))
})
}
}
m := Map()
m[1,2,3] := 123
m["a","b","c"] := "abc"
msgbox m[1,2,3]
msgbox m["a","b","c"]
Re: [a108] N-dimensional map.
Posted: 10 May 2023, 16:34
by FanaticGuru
ntepa wrote: ↑08 May 2023, 19:25
FanaticGuru wrote: ↑08 May 2023, 15:23
Could you show me how to convert this so that it modifies the Map base object through prototype other than extending it with MapN?
Code: Select all
class MultiDimMap {
static __New() {
__set := Map.Prototype.GetOwnPropDesc("__Item").set
__get := Map.Prototype.GetOwnPropDesc("__Item").get
Map.Prototype.DefineProp("__Item", {
get:(self, k1, p*) => p.Length
? __get(self, k1)[p*]
: __get(self, k1),
set:(self, value, k1, p*) => (p.Length && (
!(Map.Prototype.Has)(self, k1)
|| !(__get(self, k1) is Map)
) && __set(self, (m:=Map(), m.CaseSense:=self.CaseSense, m), k1),
p.Length
? __get(self, k1)[p*] := value
: __set(self, value, k1))
})
}
}
m := Map()
m[1,2,3] := 123
m["a","b","c"] := "abc"
msgbox m[1,2,3]
msgbox m["a","b","c"]
@ntepa this is some super cool mind bending code. After staring at it for about 30 minutes (after already understanding Helgef code), I understand how the proto stuff is working but I was pretty far from creating it myself. This kind of code is kind of tough to figure out a piece at a time. This does continue to flesh out my baseline knowledge of working with prototypes that will hopefully make it where I am better at this stuff on my own in the future.
Here is a condensed fat arrow version for those that might want something that just works to drop in their library.
Code: Select all
; Helgef: An "n-dimensional" map; ntepa: Map.Prototype Class; FanaticGuru: fat arrow Function
; https://www.autohotkey.com/boards/viewtopic.php?p=520860#p520860
MapN() => (__set := Map.Prototype.GetOwnPropDesc("__Item").set, __get := Map.Prototype.GetOwnPropDesc("__Item").get, Map.Prototype.DefineProp("__Item", { get: (self, k1, p*) => p.Length ? __get(self, k1)[p*] : __get(self, k1), set: (self, value, k1, p*) => (p.Length && (!(Map.Prototype.Has)(self, k1) || !(__get(self, k1) is Map)) && __set(self, (m := Map(), m.CaseSense := self.CaseSense, m), k1), p.Length ? __get(self, k1)[p*] := value : __set(self, value, k1)) }))
MapN ; Initialize in Script before using Map
m := Map()
m[1, 2, 3] := 123
m["a", "b", "c"] := "abc"
MsgBox m[1, 2, 3]
MsgBox m["a", "b", "c"]
I made it a function because several other prototype things I have that do similar stuff are functions.
The self initializing of a class is pretty nice but I like putting these type items at the end of my script and I would have to initialize it anyways. I did not even know about
static __New being called automatically when a class is defined until I went looking in the documents to understand this script. I miss that feature of v1 of statics being initialized during script startup.
FG
Re: [a108] N-dimensional map.
Posted: 12 May 2023, 12:58
by Helgef
Re: [a108] N-dimensional map.
Posted: 12 May 2023, 14:06
by FanaticGuru
Helgef wrote: ↑12 May 2023, 12:58
also,
Well, yea, there is that.
Luckily, I did not think of that at first or I would not have learned nearly as much.
FG
Re: [a108] N-dimensional map.
Posted: 14 Aug 2023, 07:41
by 20170201225639
Great function, thanks!
Now is there an easy way to extend this so it's possible to check if a particular "path" exists? For example, in v1 it's possible to write:
Code: Select all
multi_d_key := [4,2,8]
if multi_d_array[multi_d_key*]
{
; path exists
}
Currently I can use map_n to assign value very conveniently. But when I try if a path exists an error is thrown. Well, maybe I can just try-catch it, but I'm wondering if there's another way...