Why is the key of my Associative Array a reference to a string and not the string itself? - autohotkey

I have the following string that contains product barcodes:
4016241030924;4016241030924;8710624237479;5900951254741;8710398162939;8710398162939;8710398162939;8710398162939;8710398162939;8710398162939;8710398162939;8710398162939;8710624296933;8710624296872;8710624223885;8710624223885;8711000341001;8711000341001;8711000341001;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260453;
What I want to do is:
Split the string by ;
Create an Associative Array where the key is the barcode and the value is the count of the barcode
Loop through the Associative Array and print the key (= barcode) and the value (= count)
Here's what I am trying:
BarcodesAssArray := Array()
BarcodeArray := StrSplit(fileContent, ";")
Loop % BarcodeArray.MaxIndex() - 1 {
thisBarcode := BarcodeArray[a_index]
; Check if barcode already exists
if (BarcodesAssArray[thisBarcode]) {
BarcodesAssArray[thisBarcode] := BarcodesAssArray[thisBarcode] + 1
} else {
BarcodesAssArray[thisBarcode] := 1
}
}
For key, value in BarcodesAssArray
MsgBox, %key% = %value%
But instead of the key being the barcode it is some sort of reference to the barcode. This is what I get:
-333809963 = 1
204486651 = 8
430547597 = 2
430561191 = 1
430584127 = 9
43084165 = 1
...
What I expect to get is:
4016241030924 = 2
8710624237479 = 1
8710398162939 = 8
...
What should I do differently?

Try to simplify the code and take it one step at time
BarcodesAssArray := 4016241030924;4016241030924;8710624237479;5900951254741;8710398162939
BarcodeArray := StrSplit(BarcodesAssArray, ";")
MsgBox BarcodeArray(1) BarcodeArray(2) BarcodeArray(3) BarcodeArray(4) BarcodeArray(5)
This will at least get you past the StrSplit statement knowing that you have a valid array
I haven't coded in a while so run at your own risk :)

"Your problem is probably occurring because the keys in your arrays are being treated as numeric. There are limits on the size of numeric keys, depending on whether you are using 32 bit AutoHotkey or 64 bit. The way I would fix this is to cause the keys to be treated as alpha by appending a constant alpha value to the key in the array and stripping it off when displaying, etc the key. This also deals with the case where leading zeros would otherwise be stripped from the numeric keys."
TAC109 - https://www.autohotkey.com/boards/viewtopic.php?p=312566#p312566
BarcodesString := "4016241030924;4016241030924;8710624237479;5900951254741;8710398162939;8710398162939;8710398162939;8710398162939;8710398162939;8710398162939;8710398162939;8710398162939;8710624296933;8710624296872;8710624223885;8710624223885;8711000341001;8711000341001;8711000341001;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260453;"
BarcodesString := RTrim(BarcodesString,";") ; remove trailing ;
BarcodesAssArray := {}
Loop, Parse, BarcodesString, `;
switch BarcodesAssArray.HasKey(A_LoopField . "")
{
case true:BarcodesAssArray[A_LoopField . ""] += 1
case false:BarcodesAssArray[A_LoopField . ""] := 1
}
For key, value in BarcodesAssArray
MsgBox, %key% = %value%
Xtra - https://www.autohotkey.com/boards/viewtopic.php?p=312565#p312565

Related

How can I loop thorough a record one character at a time?

How can I loop thorough a record one character at a time? I want to interrogate records in a ASCII file one character at a time looking for and replacing non-printable characters. I tried using the Loop Condition with no luck. Thanks in advance for any help.
Yes, this is possible in a DataStage Transformer.
The "Loop Condition" creates a new output row per iteration. It operates on each row it receives. You might want to add a constraint to your output link which is only true when your loop iterations are finished (for that row).
A little pseudo-code to replace every 'ä' with a '?' by looping through char-by-char:
// Input Link "DSLink2"
// provides a column named "text"
// Stage Variables:
NVarCHar(20) svLine := DSLink2.text
NChar(1) svReplacementChar := "?"
// Loop Variables:
NChar(1) lvCharToTest
Bit lvCharOK := 0
NVarCHar(20) lvNewLine := ''
Integer i := 0
// Loop Condition:
loop while (i < Len(svLine)) {
i = i + 1
lvCharToTest := svLine[i,1]
// replace by proper test condition or function according to your needs:
lvCharOK := lvCharToTest = 'ä'
if (lvCharOK) {
lvNewLine = lvNewLine + lvCharToTest
}
else {
lvNewLine = lvNewLine + svReplacementChar
}
}
// DSLink4_output:
If (i = Len(svLine)) {
DSLInk4_output.text := lvNewLine
}
Screenshot of a Transformer Stage showing this example

How to have "input" (or is it context?) dependent hotstrings/hotkeys ?

I want a hotkey or hotstring (whatever is easier), so I can easily convert e.g.
1:5 into [1,2,3,4,5] or
3:7 into [3,4,5,6,7] etc..
I want this to work for all integers...
So I want "multiple variants of the same hotstring" (or, if easier: a hotkey that works somewhat similar: e.g. pressing strg + h and typing 1:3 should produces [1,2,3] )
It should recognize that I typed a number followed by colon followed by another number, and then expand correspondingly..
I looked into the Input function, but it does not seem to be exactly what I want..
I don't need a working solution. Hints & links or keywords for further googling are already helpful..
After typing +h or pressing strg+h, type two numbers to produce the desired outcome:
:*:+h::
^h::
nr := "" ; empty variable's content
end_nr := ""
Input, var, L2 ; Length limit=2
; Input, var, L2 V ; V: Visible
If var is not integer
{
MsgBox, "%var%" is not integer
return
}
first_nr := SubStr(var, 1, 1)
second_nr := SubStr(var, 0)
if (first_nr >= second_nr)
{
MsgBox, "%first_nr%" is greater or equal "%second_nr%"
return
}
Loop
{
nr++ ; increase the number in the variable "nr" by 1 in each iteration
if (nr < first_nr)
continue
If (nr = second_nr)
break
end_nr .= nr . "," ; concatenate the outputs by adding a comma to each one
}
If (first_nr = 0)
MsgBox, "0,%end_nr%%second_nr%"
else
MsgBox, "%end_nr%%second_nr%"
return

How to iterate an associative array

If I have the following associative array how do I cycle through each element of the array. So that I can print out each element
arr := {Name:MyName,Email:MyEmailAddress,Date:TheDate}
I have tried the following:
enum := arr._NewEnum()
While enum[key, value]
{
t .= key "=" value "`n"
}
MsgBox % t
But nothing is displayed
You aren't storing strings in the array, but variables that weren't defined, so nothing is displayed.
Store strings and/or numbers:
arr := {Name:"MyName",Email:"MyEmailAddress",Date:1234567}
Then use a for loop:
for key, value in arr
{
MsgBox, %key% = %value%
}

Alphabetizing a List

I'm looking for a way to truly alphabetize a list. Assuming it's a list of basic words, such as:BlackGreenThe RedBlueWaxyLivingPorousSolidLiquidVioletIs there a way to modify this code to alphabetize the list where "The Red" comes before "Solid"? Here's what I have so far:
SaveVar=%ClipboardAll%
Clipboard=
Send ^c
ClipWait, 0.5
Sort clipboard, CL
;Process exceptions
Sort := RegExOmit (Sort, "The")
Send ^v
Sleep 100
Clipboard=%SaveVar%
SaveVar=
return
Write a custom comparison function that ignores the starting "The " substring.
list = Black`nGreen`nThe Red`nBlue`nWaxy`nLiving`nPorous`nSolid`nLiquid`nViolet`nThe Azure
Sort , list , F Compare
MsgBox, %list%
Compare( a , b )
{
arem := RegExReplace(a, "A)The " , "" )
brem := RegExReplace(b, "A)The " , "" )
return arem > brem ? 1 : arem < brem ? -1 : 0
}
Regular expressions are used to remove the substring "The " from the string and the result stored in a temporary string, which is then used for comparison.
The substring must start at the beginning of the string, regex option A), and must include a space immediately after The.

Remove last n characters of string after the dot with Autohotkey

I am using Autohotkey.
I have a string that looks like this S523.WW.E.SIMA. I want to remove the last few characters of the string after the dot (including the dot itself). So, after the removal, the string will look like S523.WW.E.
This may look like a simple question but I just cannot figure out using the available string functions in Autohotkey. How can this be done using Autohotkey? Thank you very much.
Example 1 (last index of)
string := "S523.WW.E.SIMA"
LastDotPos := InStr(string,".",0,0) ; get position of last occurrence of "."
result := SubStr(string,1,LastDotPos-1) ; get substring from start to last dot
MsgBox %result% ; display result
See InStr
See SubStr
Example 2 (StrSplit)
; Split it into the dot-separated parts,
; then join them again excluding the last part
parts := StrSplit(string, ".")
result := ""
Loop % parts.MaxIndex() - 1
{
if(StrLen(result)) {
result .= "."
}
result .= parts[A_Index]
}
Example 3 (RegExMatch)
; Extract everything up until the last dot
RegExMatch(string, "(.*)\.", result)
msgbox % result1
Example 4 (RegExReplace)
; RegExReplace to remove everything, starting with the last dot
result := RegExReplace(string, "\.[^\.]+$", "")