How to check if string is contained in an array in AutoHotKey - arrays

I have following code:
ignored := [ "Rainmeter.exe", "Nimi Places.exe", "mumble.exe" ]
a := ignored.HasKey("mumble.exe")
MsgBox,,, %a%
It returns 0 even though the string is clearly present in the array.
How do I test if a string value is present in an array?
PS: I also tried if var in which gives same results.

You can't, using just one command. Such functionality is not implemented in AHK_L as of 1.1.22.3.
You'll have to either define your own function
hasValue(haystack, needle) {
if(!isObject(haystack))
return false
if(haystack.Length()==0)
return false
for k,v in haystack
if(v==needle)
return true
return false
}
or use some fancy workaround:
ignored := { "Rainmeter.exe":0, "Nimi Places.exe":0, "mumble.exe":0 }
msgbox, % ignored.HasKey("mumble.exe")
This would create an associative array and put your values as keys (the values are set to 0 here), so the .HasKey() makes sense to use.

Related

Google Script is returning the index of the array but I need the value

I have a google spreadsheet that gets data logged to it via a google form.
When the form is logged each time, it triggers a script that gets values from a certain section using:
var tabNumsVal = sheet.getSheetValues(lastRow, tabOneCol.getColumn(), 1, 6)[0];
When I check the array, I can see that the array has the values such as:
0: 12
1: 24
2: 26W
3: 0
4: 0
5: 0
However when I use the following command, it puts the index numbers (0 to 5) into the array instead of the values in the array.
var tabNumsFinal = [];
for (var tabard in tabNumsVal) {
if (tabard !== "") {
tabNumsFinal.push(tabard);
}
}
It used to work but I have had to upgrade my code to Google Script v8 and it seems that this has broken the code.
I had to alter the 'for each' code block to a 'for' code block and it seems this is handling the values differently.
I am quite sure this is simple for many people but I really only touch Google Script 1 time each year. I have tried using Logger.log(tabard) to output the data to the execution log, but it just traverses the code and doesn't output anything. I figured this might be because of the !== "" operator, so I placed it above the if statement but still inside the for statement and it still outputs nothing.
I tried using Logger.log(tabNumsVal) and Logger.log(tabNumsFinal) and again it output nothing.
To recap:
The data from the form is returning correctly into the columns of the spreadsheet, hence it is showing inside the array properly. It's just that the index numbers are being output instead of the values from the array.
Since you're using for in loop, tabard is the index here.
var tabNumsFinal = [];
for (var i in tabNumsVal) {
let val = tabNumsVal[i];
if (val !== "") {
tabNumsFinal.push(val);
}
}
For in loop

Ruby variable regular expression in Array Select

I'm trying to exclude elements from an array of strings using array.select. I have this method:
def filter_out_other_bad_vals(array_of_strs, things_i_want)
array_of_strs = array_of_strs.select { |line| /"#{things_i_want}"/.match(line) }
end
I want to pass a string as a variable things_i_want. But this does not return any matches:
array = ["want_this", "do_not_want", "do_not_want","want_this", "want_this"]
pattern = 'want_this'
array = filter_out_other_bad_vals(array, pattern)
This returns an empty array. But if I hardcode the value in the match expression, I get what I want.
def filter_out_other_bad_vals(array_of_strs, things_i_want)
array_of_strs = array_of_strs.select { |line| /want_this/.match(line) }
end
How do I put a variable in the regex? What am I doing wrong?
I could just traverse the array, check each item, and then save the value in another array, but that's not very ruby-like, is it?
You include quotes in regex definition:
/"#{things_i_want}"/
remove them and it should work:
/#{things_i_want}/
EDIT:
By the way, you don't have to use regex for exact matching, you can use equality check (==) or #include? depending if you need a string to be equal to thing you want or just include it:
> array = ["want_this", "do_not_want", "do_not_want","want_this", "want_this"]
> array.select{|line| line == 'want_this'}
# => ["want_this", "want_this", "want_this"]
> array.select{|line| line.include? 'want_this'}
# => ["want_this", "want_this", "want_this"]

Why this code is generating array index out of bound?

I am stuck for past 5 - 6 hours in figuring this out that why this code is generating array index out of bound error on run time. I am unable to find out the reason. Can you please tell what modifications are required to correct this code?
spotsArr := make(map[int][]map[int64][]int)
for ind, availableSpot := range availableSpots {
spotsArr[availableSpot.Uid][ind] = make(map[int64][]int)
spotsArr[availableSpot.Uid][ind][availableSpot.Date] = []int{availableSpot.SpotSlug}
}
fmt.Println(spotsArr)
Edit 1: View the full code here https://play.golang.org/p/Smm0BFgtNp
Edit 2: Actually what I need to do is to get output in format something like:
{ uid: { date: {spot_slug, spot_slug} } }
{ 86: { 1536710400: {1000, 1200, 900},
{ 1536105600: {900} } }
The error is, as the error message suggests, because you tried to assign element on the index greater than the slice length. For the sake of getting the error away, you can just initialize the slice to the length, at least, as much as the index you wanted to use :
....
spotsArr[availableSpot.Uid] = make([]map[int64][]int, ind+1, ind+1)
spotsArr[availableSpot.Uid][ind] = make(map[int64][]int)
....
But as you clarified further about the desired output, it seems that you don't need slice in the first place. You need map of Uid where each key has value of map of Date :
spotsArr := make(map[int]map[int64][]int)
for _, availableSpot := range availableSpots {
if _, ok := spotsArr[availableSpot.Uid]; !ok {
spotsArr[availableSpot.Uid] = make(map[int64][]int)
}
spotsArr[availableSpot.Uid][availableSpot.Date] = append(spotsArr[availableSpot.Uid][availableSpot.Date],availableSpot.SpotSlug)
}
fmt.Println(spotsArr)
playground
Given the last two data have the same date, the output is as follows :
map[86:map[1534896000:[900] 1535500800:[900] 1536105600:[900] 1537315200:[900 900]]]
spotsArr is a map of int to an array of maps - map[int][]...
spotsArr := make(map[int][]map[int64][]int)
On this line, you try to assign to an index of that array which has no members yet:
spotsArr[availableSpot.Uid][ind] = make(map[int64][]int)
You're saying set this spot availableSpot.Uid to something (fine) but then set the index ind in an array which doesn't have members to something else (not fine). To fix this I'd recommend trying to do less on each line so that it's much clearer where and what the problem is. You could do this to fix the grammar error:
spotsArr[availableSpot.Uid] = []map[int64][]int{make(map[int64][]int)}
But I can't think why you want to set an index on the map to the index of the Uids you're traversing (your code doing [Ind]). I'd try to make this less complex and confusing if you can and spread it out on several lines to make the intent clear.
PS Give people a code sample which runs (i.e. include all the structs used), it makes it easier to help.
PPS Thanks for code sample, that makes it clearer.

How to check for Hash value in an array?

Heres my set up
project_JSON = JSON.parse
teamList = Array.new
project = Hash.new()
project["Assignee Name"] = issue["fields"]["assignee"]["displayName"]
project["Amount of Issues"] = 0
if !teamList.include?(issue["fields"]["assignee"]["displayName"])
project_JSON.each do |x|
project["Amount of Issues"] += 1
teamList.push(project)
end
Im having trouble with this line.
if !teamList.include?(issue["fields"]["assignee"]["displayName"])
It always returns true even after the .push. I want to make an array of my team members and list how many times their name appears in my JSON. What am I doing wrong and how do I dynamically refer to a hash value in an if statement(thats where I think its wrong because if I am saying .include?(issue["fields"]["assignee"]["displayName"]) wrong then its nil and the if statement will always be true)?
In your code teamList is an empty array, so it does not include? anything, it will always return false. Now because you are using ! operator it always returns true.
EDIT
If understood it right, you have to loop through the array checking each element for the value specified.
Below is a way to do it, mind you I replaced keys for symbols as it's a good practice in Ruby:
issue = {
:fields => {
:assignee => {
:displayName => 'tiago'
}
}
}
teamList = Array.new
def teamList.has_assignee?(assignee)
self.each do |e|
return e[:assignee] == assignee
end
false
end
project = Hash.new
project[:assigneeName] = issue[:fields][:assignee][:displayName]
project[:amountOfIssues] = 0
teamList.push(project) unless teamList.has_assignee? issue[:fields][:assignee][:dsiplayName]
teamList.push(project) unless teamList.has_assignee? issue[:fields][:assignee][:dsiplayName]
puts teamList.inspect # only one object here
As Sergio pointed out you could use .detect
def teamList.has_assignee?(assignee)
self.detect { |e| e[:assigneeName] == assignee }
end

why is the index of the one-dimensional array changing this way?

I'm a beginner and I'm encountering a problem with an index of a one-dimensional array of strings (m_nameList in the code) that I'm struggling to understand. I have one method (in a class of a Windows Form Application that is not the MainForm) that returns FALSE if a string of the array at a certain index is empty, and viceversa. It looks like this:
Public Function IsReserved(index As Integer) As Boolean
Dim reserved As Boolean = False
If (Not String.IsNullOrEmpty(m_nameList(index))) Then
reserved = True
Else
reserved = False
End If
Return reserved
End Function
I have also a method on the MainForm that calls for it, and if the first method returns true then the second one displays a dialog box, otherwise it doesn't (lstResults is a listbox that has for items the strings of the array):
Private Function CheckIfSeatIsAlreadyReserved() As Boolean
Dim reserved As Boolean = m_seatMngr.IsReserved(lstResults.SelectedIndex)
If (reserved) Then
Dim msgBox As Integer = MessageBox.Show("The seat is already reserved. Would you like to continue?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
If (msgBox = DialogResult.Yes) Then
Return True
Else
Return False
End If
Else
Return True
End If
End Function
The problem I find is: if as in the code of the first method above I don't initialize index to any value, the second method will work perfectly, but I'll get a runtime error if I don't select any item on the listBox (and therefore index = -1). On the other hand, if I initialize index to 0 or to m_nameList.Length, then the program won't have any problems if I don't select any item on the ListBox and it will nicely display a warning message I wrote for that case, BUT the second method will behave in a weird way: it will find ALL the strings of the array full even if I only "write" the first one, or it will find ALL the strings empty if I "write" any string that it's not the first one (by writing I mean that I call for a method that puts my input as the text of the string selected). Any idea on why this happens and how I can fix it? Thank you so much.
I will get to the answer below, follow the logic, lets look at your first method. You can refactor it to
Public Function IsReserved(index As Integer) As Boolean
Return Not String.IsNullOrEmpty(m_nameList(index))
End Function
Everything else is called "noise". But as Fabio pointed, what if index is bad? Lets add useful code
Public Function IsReserved(index As Integer) As Boolean
If index < 0 OrElse index > m_nameList.Length - 1 Then
Throw New ArgumentOutOfRangeException(". . . . .")
End If
Return Not String.IsNullOrEmpty(m_nameList(index))
End Function
If you get this exception, your program has a bug - and you know to fix the consumer of this function.
And now lets get to your message
second method will behave in a weird way: it will find ALL the strings of the array full even if I only "write" the first one, or it will find ALL the strings empty if I "write" any string
Most likely reason why it happens - simply because you create condition when you send same value over and over again. Therefore result is same. And this is most likely a bug
If (reserved) Then
. . . . . .
Else
Return True ' <---- BUG ALLERT
End If
And two more things, your second method can shrink down to 1 line too.
Private Function CheckIfSeatIsAlreadyReserved() As Boolean
Return m_seatMngr.IsReserved(lstResults.SelectedIndex) AndAlso _
DialogResult.Yes = MessageBox.Show("The seat is already reserved. Would you like to continue?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
End Function
And, if you do some sort of reservation, array is not really good idea. How about Dictionary(Of String, Boolean)? Your theater or airplane has bunch of seats and you pre-load your dictionary with those
d.Add("1A", False)
d.Add("1B", False)
d.Add("1C", False)
d.Add("1D", False)
d.Add("1E", False)
d.Add("1F", False)
This is your whole airplane row. Now you can do much more with it

Resources