This question was answered at the bottom of this post.
I have looked at 6 different web pages from the AHK forums asking this question, and another one on SO here:
String to Number using autohotkey
...but none of them are working for me. I'm just trying to subtract a number from a string that has been grabbed from the StringSplit function. This is my code:
; Assign entry price variable.
StringSplit, prices, Window1Text, `n
MsgBox, Your entry price is %prices32%.
; Assign Stop Loss variable
SLPrice := %prices32% -= 0.10
MsgBox, Your SLPrice is %SLPrice%.
I receive the error "The following variable name contains an illegal character" on the line "SLPrice := %prices32% -= 0.10", so then I try:
; Assign entry price variable.
StringSplit, prices, Window1Text, `n
MsgBox, Your entry price is %prices32%.
; Assign Stop Loss variable
SLPrice = %prices32% - 0.10
MsgBox, Your SLPrice is %SLPrice%.
...to which I get the output:
Your SLPrice is 7.450 - 0.10
So it just displays the formula as a text string, it doesn't actually do the calculation.
Thoughts? Thanks!
UPDATE
To continue working out this solution, here is my full code up to the part I'm having an issue with, along with screenshots of what's happening:
; Get the latest window text to parse values from it
WinGetText, Window1Text, ahk_class WindowsForms10.Window.8.app.0.f96fc5_r9_ad1
MsgBox, The text is: %Window1Text% ; Displays the window get text values
Sleep, 5
; Assign entry price variable.
StringSplit, prices, Window1Text, `n
MsgBox, Your entry price is %prices32%.
; Assign Stop Loss variable
SLPrice := prices32 - 0.10
MsgBox, Your SLPrice is %SLPrice%.
ANSWER
Thanks to the contributor below, we discovered that there was a "." from the first MsgBox messing up the SLPrice variable, so we updated the SLPrice variable to read:
SLPrice := SubStr(Trim(prices32), 1, 5) - 0.10 ; to pull the left 5 characters
Thanks!
You are on the right track. But, per my comment, note := implies expressions including variable expressions (hence no surrounding %'s):
; Assign entry price variable.
StringSplit, prices, Window1Text, `n
MsgBox, Your entry price is %prices32%.
; Assign Stop Loss variable
; Note, the 32 line also includes non printing characters
; so must be trimmed and then we take the left 5 characters
SLPrice := SubStr(Trim(prices32), 1, 5) - 0.10
MsgBox, Your SLPrice is %SLPrice%.
Should do it . . .
And note, using something := %myvariable% implies reading the contents of a variable named myvariable and using those contents as the variable name. So if myvariable is "test", you are really saying something := test (where something ends up being equal to the contents of the test variable).
Hth,
EDIT per below, here is a working example (BUT PER LATTER COMMENT, SEE BELOW, TOO):
Window1Text =
(
25
26
27
28
)
; Assign entry price variable.
StringSplit, prices, Window1Text, `n
MsgBox, Your entry price is %prices2%. ; using only 2nd line (26)
; Assign Stop Loss variable
SLPrice := prices2 - 0.10 ; again, changed to 2nd line
MsgBox, Your SLPrice is %SLPrice%. ; 25.900000
clipboard := SLPrice
HTH,
FURTHER EDIT: Because this is really cool and illustrates the several concepts as to how they relate to pseudo array variable expressions:
Window1Text =
(
25
26
27
28
)
; Assign entry price variable.
StringSplit, prices, Window1Text, `n ; (prices0 is the number of entries)
InputBox, num,, % "Pick an array number from 1 to " prices0 ; get the array number
; note the variable expression includes the num variable contents
MsgBox, % "Your entry price is " Trim(prices%num%) "." ; depends on array number
; Assign Stop Loss variable
SLPrice := Trim(prices%num%) - 0.10 ; uses the array number value
MsgBox, Your SLPrice is %SLPrice%. ; so depends on the array number
clipboard := SLPrice
Right?
But note, these testers work easily. The real life example from the OP is copied text and the line 32 contains non-printing characters dealt with by Trim(x) and taking only the first few characters from Left with SubStr(x,1,5).
Related
I have been reading a text file a object and create a list with the contents.
textfile:
Activity Time Location
Football 8-9 Pitch
Basketball 9-10 Gym
Lunch 11-12 Home
Read 13-14 Library
Swim 14-15 Pool
openTime = 6
closeTime = 15
come = int(input('When do you want to come?'))
leave = int(input('When do you want to leave?'))
# endtime_of_activity and startTimeofactivity is equal to the startingtime
# of each activity and the end time of each activity in the textfile
# (taken from a list that I have been splitting).
for i in range(len(my_list)):
item = my_list[i]
if (i == 1):
continue
if closeTime <= come <= endtime_of_activity and startTimeofactivity < leave <= closeTime:
print(item.activities)
My question: As you can read in the textfile there are some activities appering on different times. For example football between 8 and 9. With the code I want to be able to skip the second element (basketball) as the code is doing, however, I want the if statement under "continue" to work. If i type that im coming 8 and leaving at 12 I want all the activities (excluding the second one) to show. This works for me when I'm doing a regular for-loop without skiping the second activity, like when im just writing: for i in my_list, then adding on the condition, but when Im doing the code above it shows me all the activites (except basketball) independeltly of when I chose to come and leave. What have I missed? How could I write the code better?
If you want to skip a certain activity, simply test if the activitiy to be printed is the same and skip it if it is:
with open("f.txt","w") as f:
f.write(("Activity Time Location\nFootball 8-9 "
"Pitch\nBasketball 9-10 Gym\nLunch 11-12"
" Home\nRead 13-14 Library\nSwim 14-15"))
data = []
with open("f.txt") as f:
for line in f:
act, time, what = (line.strip().split(" ") + ["","",""])[:3]
if data:
try:
time=list(map(int, time.split("-")))
except ValueError:
continue # invalid time: skip row
data.append([act,time,what])
header,*data = data
openTime = 6
closeTime = 15
come = 9
leave = 12
skip=set(["Basketball"])
fmt = "{:<15}"*len(header)
print(fmt.format(*header))
for act,(start,stop),what in data:
if act in skip:
continue
if start >= come and stop <= leave and openTime <= come and closeTime >= leave:
print(fmt.format(act, f"{start}-{stop}", what))
Output:
Activity Time Location
Football 8-9 Pitch
Lunch 11-12 Home
In my program I keep filling the following array with data obtained from a database table then inspect it to find certain words:
01 PRODUCTS-TABLE.
03 PRODUCT-LINE PIC X(40) OCCURS 50 TIMES.
sometimes it occurs 6 times, sometimes more than 6 times.
I'd like to find the number of lines in the array every time I write data to it , how can I do that ?
I tried this but it based on a fixed length:
INSPECT-PROCESS.
MOVE 0 TO TALLY-1.
INSPECT PRODUCTS-TABLE TALLYING TALLY-1 FOR ALL "PRODUCT"
IF TALLY-1 > 0
MOVE SER-NUMBER TO HITS-SN-OUTPUT
MOVE FILLER-SYM TO FILLER-O
MOVE PRODUCT-LINE(1) TO HITS-PR-OUTPUT
WRITE HITS-REC
PERFORM WRITE-REPORT VARYING CNT1 FROM 2 BY 1 UNTIL CNT1 = 11.
WRITE-REPORT.
MOVE " " TO HITS-SN-OUTPUT
MOVE PRODUCT-LINE(CNT1) TO HITS-TX-OUTPUT
WRITE HITS-REC.
In the first output line it writes the SN and the first product-line then in the following lines it writes all remaining product-line and blank out SN.
Something like:
12345678 first product-line
Second product-line
etc
It’s working, however, it only stops when CNT1 is 11, how can I feed the procedure with a variable CNT1 based on how many lines are actually in PRODUCTS-TABLE each time?
I solved the problem by adding an array line counter (LINE-COUNTER-1) to count (ADD 1 TO LINE-COUNTER-1) how many times I add data to the array and stop writing the report when "WRITE-COUNTER = LINE-COUNTER-1"
INSPECT-PROCESS.
MOVE 0 TO TALLY-1
INSPECT PRODUCTS-TABLE TALLYING TALLY-1 FOR ALL "PRODUCT"
IF TALLY-1 > 0
MOVE HOLD-SER-NUM TO HITS-SN-OUTPUT
MOVE FILLER-SYM TO FILLER-O
MOVE PRODUCT-LINE(1) TO HITS-PR-OUTPUT
WRITE HITS-REC
PERFORM WRITE-REPORT VARYING WRITE-COUNTER FROM 2 BY 1
UNTIL WRITE-COUNTER = LINE-COUNTER-1.
I have a table with students exams scores;
veriables: name, score1, score2, score3 and gender
wherever there is a missing value in one of the scores,
the score is set to 999.
I want to transform all 999's to missing (.) values.
I realized there are 2 main ways and I would like to know the MAIN difference between them.
As written above, both give the same output:
first:
data try ;
set mis_999 ;
if score1 = 999 then score1 = . ;
if score2 = 999 then score2 = . ;
if score3 = 999 then score3 = . ;
run ;
second (with array):
data array_try ;
set mis_999 ;
array try2{*} score1-score3 ;
do i=1 to dim(try2) ;
if try2(i) = 999 then try2(i) = . ;
end ;
run ;
For that example the main difference is that the code using an array is easier to expand to more variables.
In your first example you have what is referred to as wallpaper code, a lot of code that repeats the same pattern. If you have 500 variables instead of 3 you would need to write 500 statements. But with the array method you would just need to change the list of variables in the array definition. The DO loop would be the same.
I work at a doctors office doing the billing, and I've been writing code to streamline the billing process. I must include all diagnoses in the billing software, so I copy the whole chart, and parse it into an array by newlines looking for the prefix ICD-10, and if two codes are on the same line, it separates those too (via a comma). Before that, it removes a part (if it exists) of the chart that includes canceled procedures so the canceled procedures aren't charged. Sometimes, multiple of the same diagnosis is included in the chart for the purpose of ordering a procedure (it's automatic), and I need to only add each diagnosis to the array once.
[...]
SendInput, ^a
ClipBoard :=
SendInput, ^c
ClipWait
BlockInput, MouseMoveOff
lString := ClipBoard
Sleep, 200
IfInString, lString, Canceled Orders
{
lStringLeft := SubStr(lString, 1, InStr(lString, "Canceled Orders")-1)
Sleep, 20
lStringRight := SubStr(lString, InStr(lString, "Allergies as of"))
Sleep, 20
lString :=
Sleep, 20
lString := lStringLeft
Sleep, 20
lString .= lStringRight
Sleep, 20
}
DxArr := []
numDx := 0
Loop, Parse, lString, `n
If InStr(A_LoopField, "ICD-10")
Loop, Parse, A_LoopField, `,
DxArr[++numDx] := Trim(SubStr(A_LoopField, InStr(A_LoopField, ":") + 1), " `t`n`r")
[...]
The ideal output for
Essential Hypertension
ICD-9-CM: 401.0
ICD-10-CM: I10
Essential Hypertension with Chronic Kidney Disease, Stage 3
ICD-9-CM: 585.3, 401.0
ICD-10-CM: N18.3, I10
is
I10 N18.3
I've been at this with several different solutions I found on the internet, but so far, they've just made a mess rather than actually fixing any problem. Any help is appreciated!
Use a hash to remove duplicates. Use your code as the key and a dummy for the value. I use "true" below as the dummy value. Duplicate records have the same key so they replace the previous key-value pair.
Output the hash's keys after you are done parsing the input.
DxHash := {}
Loop, Parse, lString, `n
If InStr(A_LoopField, "ICD-10")
Loop, Parse, A_LoopField, `,
DxHash[Trim(SubStr(A_LoopField, InStr(A_LoopField, ":") + 1), " `t`n`r")] := true
for diagnosis,dummy in DxHash
send %diagnosis%{SPACE}
Hello Everyone,
I have two files File1 and File2 which has the following data.
File1:
TOPIC:topic_0 30063951.0
2 19195200.0
1 7586580.0
3 2622580.0
TOPIC:topic_1 17201790.0
1 15428200.0
2 917930.0
10 670854.0
and so on..There are 15 topics and each topic have their respective weights. And the first column like 2,1,3 are the numbers which have corresponding words in file2. For example,
File 2 has:
1 i
2 new
3 percent
4 people
5 year
6 two
7 million
8 president
9 last
10 government
and so on.. There are about 10,470 lines of words. So, in short I should have the corresponding words in the first column of file1 instead of the line numbers. My output should be like:
TOPIC:topic_0 30063951.0
new 19195200.0
i 7586580.0
percent 2622580.0
TOPIC:topic_1 17201790.0
i 15428200.0
new 917930.0
government 670854.0
My Code:
import sys
d1 = {}
n = 1
with open("ap_vocab.txt") as in_file2:
for line2 in in_file2:
#print n, line2
d1[n] = line2[:-1]
n = n + 1
with open("ap_top_t15.txt") as in_file:
for line1 in in_file:
columns = line1.split(' ')
firstwords = columns[0]
#print firstwords[:-8]
if firstwords[:-8] == 'TOPIC':
print columns[0], columns[1]
elif firstwords[:-8] != '\n':
num = columns[0]
print d1[n], columns[1]
This code is running when I type print d1[2], columns[1] giving the second word in file2 for all the lines. But when the above code is printed, it is giving an error
KeyError: 10472
there are 10472 lines of words in the file2. Please help me with what I should do to rectify this. Thanks in advance!
In your first for loop, n is incremented with each line until reaching a final value of 10472. You are only setting values for d1[n] up to 10471 however, as you have placed the increment after you set d1 for your given n, with these two lines:
d1[n] = line2[:-1]
n = n + 1
Then on the line
print d1[n], columns[1]
in your second for loop (for in_file), you are attempting to access d1[10472], which evidently doesn't exist. Furthermore, you are defining d1 as an empty Dictionary, and then attempting to access it as if it were a list, such that even if you fix your increment you will not be able to access it like that. You must either use a list with d1 = [], or will have to implement an OrderedDict so that you can access the "last" key as dictionaries are typically unordered in Python.
You can either:
Alter your increment so that you do set a value for d1 in the d1[10472] position, or simply set the value for the last position after your for loop.
Depending on what you are attempting to print out, you could replace your last line with
print d1[-1], columns[1]
to print out the value for the final index position you currently have set.