[a108] N-dimensional map.
[a108] N-dimensional map.
To allow storing values at any depth, eg, myMap[1,2,3] := myValue.
See github for source and example. Please report any problems.
Cheers.
See github for source and example. Please report any problems.
Cheers.
- FanaticGuru
- Posts: 1906
- Joined: 30 Sep 2013, 22:25
Re: [a108] N-dimensional map.
Helgef wrote: ↑30 Mar 2020, 09:39To allow storing values at any depth, eg, myMap[1,2,3] := myValue.
See github for source and example. Please report any problems.
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
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
Re: [a108] N-dimensional map.
thanks for the feedback, glad you liked it.
Cheers.
Cheers.
- FanaticGuru
- Posts: 1906
- Joined: 30 Sep 2013, 22:25
Re: [a108] N-dimensional map.
Helgef wrote: ↑30 Mar 2020, 09:39To allow storing values at any depth, eg, myMap[1,2,3] := myValue.
See github for source and example. Please report any problems.
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
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
Re: [a108] N-dimensional map.
FanaticGuru wrote: ↑08 May 2023, 15:23Could 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"]
- FanaticGuru
- Posts: 1906
- Joined: 30 Sep 2013, 22:25
Re: [a108] N-dimensional map.
@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.ntepa wrote: ↑08 May 2023, 19:25FanaticGuru wrote: ↑08 May 2023, 15:23Could 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"]
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
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
Re: [a108] N-dimensional map.
also,
Cheers.
Code: Select all
map.prototype := map_n.prototype
- FanaticGuru
- Posts: 1906
- Joined: 30 Sep 2013, 22:25
Re: [a108] N-dimensional map.
Well, yea, there is that.
Luckily, I did not think of that at first or I would not have learned nearly as much.
FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
-
- Posts: 144
- Joined: 01 Feb 2017, 22:57
Re: [a108] N-dimensional map.
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:
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...
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
}