Alternatives to a very long sequence of if statements

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
sd9225

Alternatives to a very long sequence of if statements

25 Sep 2018, 18:43

Hi all, I mostly use AHK to implement keyboard shortcuts for myself; for example, pressing ctrl+shift+hyphen followed by a letter inserts the unicode character for that letter with a macron (ā, ḇ, ē, ḡ, etc). I'm achieving this this with "if" and "else if" statements, but I'd like to find a more compact, more elegant solution if one exists.

Here's an example of one of my keyboard shortcut scripts. Some of the characters may not render correctly if you don't have a full Unicode font available.

Code: Select all

^+-::
input, c1, L1 ;
if ( c1 == " " )
    Send % Chr(0x0304) ; Combining macron
else if ( c1 == "A" )
    Send Ā
else if ( c1 == "a" )
    Send ā
else if ( c1 == "B" )
    Send Ḇ
else if ( c1 == "b" )
    Send ḇ
else if ( c1 == "D" )
    Send Ḏ
else if ( c1 == "d" )
    Send ḏ
else if ( c1 == "E" )
    Send Ē
else if ( c1 == "e" )
    Send ē
else if ( c1 == "G" )
    Send Ḡ
else if ( c1 == "g" )
    Send ḡ
else if ( c1 == "I" )
    Send Ī
else if ( c1 == "i" )
    Send ī
else if ( c1 == "K" )
    Send Ḵ
else if ( c1 == "k" )
    Send ḵ
else if ( c1 == "L" )
    Send Ḻ
else if ( c1 == "l" )
    Send ḻ
else if ( c1 == "N" )
    Send Ṉ
else if ( c1 == "n" )
    Send ṉ
else if ( c1 == "O" )
    Send Ō
else if ( c1 == "o" )
    Send ō
else if ( c1 == "R" )
    Send Ṟ
else if ( c1 == "r" )
    Send ṟ
else if ( c1 == "T" )
    Send Ṯ
else if ( c1 == "t" )
    Send ṯ
else if ( c1 == "U" )
    Send Ū
else if ( c1 == "u" )
    Send ū
else if ( c1 == "Y" )
    Send Ȳ
else if ( c1 == "y" )
    Send ȳ
else if ( c1 == "Z" )
    Send Ẕ
else if ( c1 == "z" )
    Send ẕ
else
    Send _
c1 := ""
return
To condense this into some cleverer code, I figured I could use Associative Arrays. However, I'm only able to get lowercase output. Here's what I've got so far:

Code: Select all

^+-::
myArray := {"A":"Ā", "a":"ā"
          , "B":"Ḇ", "b":"ḇ"
          , "D":"Ḏ", "d":"ḏ"} ; and so on--I don't feel like typing the whole thing out right now :p
input, c1, L1
Send % myArray[c1]
c1 := ""
return
So, my questions for you are... (1) How would you condense a very long string of if statements? (2) Is there a way to get case-sensitive associative arrays?

Thanks!
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Alternatives to a very long sequence of if statements

25 Sep 2018, 19:10

- AutoHotkey arrays are case insensitive. However, you can use a case-sensitive Scripting.Dictionary object.
- I discuss various key points in my tutorial. Cheers.
jeeswg's objects tutorial - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=7&t=29232

Code: Select all

q:: ;case-sensitive array
vText := " ;continuation section
(
A:AX
B:BX
C:CX
a:ax
b:bx
c:cx
)"
oArray := ComObjCreate("Scripting.Dictionary")
Loop, Parse, vText, `n, `r
{
	oTemp := StrSplit(A_LoopField, ":")
	, oArray.Item("" oTemp.1) := oTemp.2
}
MsgBox, % oArray.Item("A")
MsgBox, % oArray.Item("a")
return
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Gabby
Posts: 28
Joined: 19 Aug 2017, 03:55

Re: Alternatives to a very long sequence of if statements

25 Sep 2018, 19:36

I do this sort of thing a lot. I tend to use what I call bar-strings, eg "AĀ|aā|...". I use StringSplit to convert this to an array, and it's easy from there.

In other cases, where the commands are used less frequently, I make a picklist dialog, so I can see what I'm doing (see attachment). The menu/picklist is defined in a separate file, loaded on the fly, so it can be context driven. So to enter my email address, I type ^#P to get the menu, then E (for the email), or eg D3 for a long date, then Enter.
Capture.PNG
(26.14 KiB) Downloaded 101 times
coffee
Posts: 133
Joined: 01 Apr 2017, 07:55

Re: Alternatives to a very long sequence of if statements

25 Sep 2018, 19:43

Sample, adjust for v1 as needed.

Code: Select all

shifted := 0
;// Place the array outside of the hotkey, it is defined globally, once,
;//	instead of repeatedly being defined every time you hit the hotkey.
myArray := {
	"a": ["ā", "Ā"],
	"b": ["ḇ", "Ḇ"],
	"d": ["ḏ", "Ḏ"]
} ; and so on--I don't feel like typing the whole thing out right now :p

;// Two hotkeys
+^-:: ;// Shifted
	shifted := 1
^-:: ;// Unshifted
	c1 := Input("L1")
	SendInput(myArray[c1][++shifted])
	c1 := ""
	shifted := 0
	return

You could also play with Ord(), checking the character code and passing the numeric index as needed, and use one hotkey.

Code: Select all

+^-::
	c1 := Input("L1")
	SendInput(myArray[c1][Ord(c1) < 91 ? 2 : 1])
	c1 := ""
	return
	
User avatar
Datapoint
Posts: 296
Joined: 18 Mar 2018, 17:06

Re: Alternatives to a very long sequence of if statements

25 Sep 2018, 20:03

Code: Select all

; Save script with "UTF-8 with BOM" encoding
charList := "A:Ā, a:ā, B:Ḇ, b:ḇ, D:Ḏ, d:ḏ"
myArray := {}
Loop, Parse, charList, `,, % A_Space
	myArray[Asc(SubStr(A_LoopField, 1, 1))] := SubStr(A_LoopField, 0)
return

^+-::
	input, c1, L1
	Send % myArray[Asc(c1)]
	c1 := ""
return
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Alternatives to a very long sequence of if statements

26 Sep 2018, 04:06

Code: Select all

; UTF-8 with BOM
^+-::sendMacron()

makeMappings() {
	static MAPPINGS = 
	(LTrim Join
		A,Ā|a,ā|B,Ḇ|b,ḇ|D,Ḏ|d,ḏ|E,Ē|e,ē|
		G,Ḡ|g,ḡ|I,Ī|i,ī|K,Ḵ|k,ḵ|L,Ḻ|l,ḻ|
		N,Ṉ|n,ṉ|O,Ō|o,ō|R,Ṟ|r,ṟ|T,Ṯ|t,ṯ|
		U,Ū|u,ū|Y,Ȳ|y,ȳ|Z,Ẕ|z,ẕ|
	)

	Arr := []

	for each, Mapping in StrSplit(MAPPINGS, "|")
	{
		Mapping := StrSplit(Mapping, ",")
		Arr.Push({"input": Mapping[1], "output": Mapping[2]})
	}

	Arr.Push({"input": " ", "output": Chr(0x0304)})

	return Arr
}

sendMacron() {
	static MAPPINGS := makeMappings()

	Input c1, L1

	for each, Mapping in MAPPINGS
	{
		if (c1 == Mapping.input)
		{
			Send % Mapping.output
			return
		}
	}

	Send _
}
just me
Posts: 9453
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Alternatives to a very long sequence of if statements

26 Sep 2018, 04:43

Code: Select all

; UTF-8 with BOM
#NoEnv
SendMode, Input
Macron := Chr(0x0304)                                 ; combining macron above
InpArr := StrSplit("AaBbDdEeGgIiKkLlNnOoRrTtUuYyZz")  ; input chars
OutArr := StrSplit("ĀāḆḇḎḏĒēḠḡĪīḴḵḺḻṈṉŌōṞṟṮṯŪūȲȳẔẕ")  ; output chars
RepArr := []                                          ; array of replacements
For I, V In InpArr
   RepArr[Ord(V)] := OutArr[I]
Return
; ===================================================
^+-::
   Input, C1, L1
   If (C1 == " ")
      Send %Macron%
   Else If (C2 := RepArr[Ord(C1)])
      Send %C2%
   Else
      Send %C1%
Return

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: No registered users and 342 guests