How to define a Map of Arrays? Topic is solved

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
User avatar
hoppfrosch
Posts: 443
Joined: 07 Oct 2013, 04:05
Location: Rhine-Maine-Area, Hesse, Germany
Contact:

How to define a Map of Arrays?

Post by hoppfrosch » 24 Nov 2022, 09:11

Hi there,

I want to define a map of arrays. What I currently do is following:

Code: Select all

keys := ["k1", "k2", "k3"]
data := ["d1", "d2", "d3", "d4", "d5", "d6"]

m := Map()
for k in keys {
	for d in data {
		if m.Has(k) {
			m[k].push(data[A_index])
		} else {
			m[k] := [data[A_Index]]
		}
	}
}
ExitApp
This works, but I don't like it - I want to avoid the inner "if m.Has(k) ..." conditional - in favor of a simple "m[k].push(data[A_index])"

Is there an easier way to define m as a Map, containing Arrays as data - preferred outside the for loops ...
Something like (Pseudocode):

Code: Select all

m:=Map(String, Arr(String))  # m is a map with strings as key and arrays of strings as value

lexikos
Posts: 9589
Joined: 30 Sep 2013, 04:07
Contact:

Re: How to define a Map of Arrays?  Topic is solved

Post by lexikos » 24 Nov 2022, 15:52

You cannot "define" a map of arrays. You must create a map and map keys to values, with each value being an array. You must define the behaviour, such as whether an array is created upon access of any key or only when a value is to be inserted. You can hide this away within the Map (or subclass) by overriding __Item and methods, but it will only change the appearance of how you use the Map. The same things will be happening under the hood.

You can avoid one key lookup (in the event that there is an array already) by using Get:

Code: Select all

a := (m.Get(k, false) || m[k] := [])
a.push(data[A_Index])

ThePeter
Posts: 49
Joined: 25 Oct 2022, 05:57

Re: How to define a Map of Arrays?

Post by ThePeter » 08 Dec 2022, 07:14

I cannot help myself observing (EDIT: incorrectly, as it turns out) that this can be further compressed (saving a variable assignment in the process):

Code: Select all

m.Get(k, m[k] := []).push(data[A_Index])
I am fully aware that this goes into Perl / write-only territory... :)
Last edited by ThePeter on 08 Dec 2022, 10:02, edited 1 time in total.

swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: How to define a Map of Arrays?

Post by swagfag » 08 Dec 2022, 07:59

then observe more, because now ure unconditionally (re-)creating a new empty array. ahk uses applicative order as its evaluation strategy

Descolada
Posts: 1138
Joined: 23 Dec 2021, 02:30

Re: How to define a Map of Arrays?

Post by Descolada » 08 Dec 2022, 09:42

If your keys are unique then perhaps also this would work:

Code: Select all

keys := ["k1", "k2", "k3"]
data := ["d1", "d2", "d3", "d4", "d5", "d6"]

m := Map()
for k in keys {
	m[k] := []
	for d in data
		m[k].push(d)
}
ExitApp

ThePeter
Posts: 49
Joined: 25 Oct 2022, 05:57

Re: How to define a Map of Arrays?

Post by ThePeter » 08 Dec 2022, 09:51

swagfag wrote:
08 Dec 2022, 07:59
then observe more, because now ure unconditionally (re-)creating a new empty array. ahk uses applicative order as its evaluation strategy
Interesting. Had to look up what applicative order means, but now I have learned something. Thanks for that.

cgx5871
Posts: 315
Joined: 26 Jul 2018, 14:02

Re: How to define a Map of Arrays?

Post by cgx5871 » 05 Sep 2023, 13:34

lexikos wrote:
24 Nov 2022, 15:52
You cannot "define" a map of arrays. You must create a map and map keys to values, with each value being an array. You must define the behaviour, such as whether an array is created upon access of any key or only when a value is to be inserted. You can hide this away within the Map (or subclass) by overriding __Item and methods, but it will only change the appearance of how you use the Map. The same things will be happening under the hood.

You can avoid one key lookup (in the event that there is an array already) by using Get:

Code: Select all

a := (m.Get(k, false) || m[k] := [])
a.push(data[A_Index])
I want to put an array arr:=[1,"a",2,"b",3,"c"]
Convert directly to map, mp:={1,"a",2,"b",3,"c"}
Any good ideas?

User avatar
boiler
Posts: 16949
Joined: 21 Dec 2014, 02:44

Re: How to define a Map of Arrays?

Post by boiler » 05 Sep 2023, 19:28

cgx5871 wrote: I want to put an array arr:=[1,"a",2,"b",3,"c"]
Convert directly to map, mp:={1,"a",2,"b",3,"c"}
Any good ideas?
Not sure if this question is really on topic for this thread, but I think you're looking to do this:

Code: Select all

arr := [1,"a",2,"b",3,"c"]
mp := Map()
for k, v in arr
	if Mod(k, 2)
		mp[v] := arr[k+1]

; display resulting map:
for k, v in mp
	MsgBox k ": " v

cgx5871
Posts: 315
Joined: 26 Jul 2018, 14:02

Re: How to define a Map of Arrays?

Post by cgx5871 » 05 Sep 2023, 20:38

@boiler
I found an easy way
mp.set(arr*)

User avatar
boiler
Posts: 16949
Joined: 21 Dec 2014, 02:44

Re: How to define a Map of Arrays?

Post by boiler » 05 Sep 2023, 20:50

Thanks. Learned something today!

lexikos
Posts: 9589
Joined: 30 Sep 2013, 04:07
Contact:

Re: How to define a Map of Arrays?

Post by lexikos » 05 Sep 2023, 22:07

Unless the map already exists, you could just use Map(arr*).

Post Reply

Return to “Ask for Help (v2)”