What is the equivalent of Java's HashMap in AutoHotkey? - hashmap

I have a set of abbreviated department names. I need to create a script which can map these abbreviations with their official titles. (For example: ADMIN → Administration)
In Java I could accomplish this using a HashMap.
public static void main() {
HashMap hm = new HashMap(); // create hash map
hm.put("ADMIN", "Administration"); // add elements to hashmap
hm.put("RAD", "Radiologist");
hm.put("TECH", "Technician");
System.out.println("ADMIN is an abbreviation for " + hm.get("ADMIN"));
}
Is there an equivalent solution for this in AutoHotkey?

You can implement key-value pairs using an Associative Array
An associative array is an object which contains a collection of
unique keys and a collection of values, where each key is associated
with one value. Keys can be strings, integers or objects, while values
can be of any type. An associative array can be created as follows:
Array := {KeyA: ValueA, KeyB: ValueB, ..., KeyZ: ValueZ}
Here is an array which uses a job's shortened name (key) to find the full display name (value).
JobArray := {ADMIN:"Administration", TECH:"Technician", RAD:"Radiologist"}
; Check if key is present
if (JobArray.HasKey("ADMIN"))
MsgBox, % "ADMIN is an abbreviation for " . JobArray["ADMIN"]
else
MsgBox, % "No display name found"

Related

Why can't I use removeAll on a list of objects?

I am trying to create an app that let's you type in what you want to eat and drink. It calculates all of that and then when you press the print button, I want it to count how often each item's in the list and give it back like this:
"9x Juice /n
5x Steaks /n
4x Salads"
The drinks and foods are objects in the new class Edibles:
class Edibles(val name: String, val price: Double):Serializable {
}
I track all of the objects in the MutableList order and can access the different members of the list and their attributes, but when I try to removeAll duplicates in my list, android studio complains and I don't know how to fix it.
My try to calculate how many members are in the list order:
var totalOrder = ""
for(i in order){
var number = order.count {it == order[0]}
totalOrder = totalOrder + "$number" + "x" + order[0].name + "\n"
order.removeAll(order[0])
}
The problem as far as I saw so far is, that Edibles doesn't have the interface Collection and when I try to implement that, it wants me to override a bunch of functions where I don't know what to do with it...
If anyone has an explanation or even a fix or an idea on how to do it differently, I would be very grateful
removeAll is meant to take a list or a predicate, not a single element. If you convert your element to a predicate checking for equality, it will remove all elements equal to that one.
order.removeAll { it == order[0] }
However, you'll also need to remember rule number one of iteration: Never delete while iterating. So what you really want to do is accumulate all of the "deletion" candidates into a list and then delete them after-the-fact.
In fact, what you're doing here can be done without mutating the list at all, using a built-in list combinator called groupBy.
var totalOrder = ""
for (entry in order.groupBy { it }) {
val item = entry.key
val count = entry.value.size
totalOrder += "${count}x${item.name}\n"
}
You're not allowed to mutate a collection while iterating it in a for loop anyway. One way to remove duplicates would be to create a temporary MutableSet and compare each item to it in a removeAll operation. removeAll takes a lambda predicate that is called on each item and the Boolean you return from the predicate. When you call add on a MutableSet, it returns a Boolean to tell you if the item already was in the set, so you can remove duplicates with the following.
Assuming you just want to compare names of items to determine if they are duplicates, you can create a MutableSet<String>.
with (mutableSetOf<String>()) {
order.removeAll { add(it.name) }
}

Groovy from 2nd dimentional array to 1 dimentional as string with prefix

I have an 2 dimentional array:
def test = [[88,3,2],[22,33,4],[88,3,3]]
test.sort
what i need now is to create each item into string and prefix it with string "test-"
so the end result would ne one dimentional array:
def endResult = ["test-88.3.2"],["test-88.3.3"],["test-22.33.4"]
if i do:
test.each {println it.join(".")}
it prints the first part but as written i need to save it and add prefix
im new to groovy any help would be great
The each method does not produce any result - it only iterates the input collection and allows you to do something with each element (e.g. print it to the console like in the example you showed in your question.)
If you want to manipulate each element of the collection and store it as a new collection, you can use the collect method which also takes a closure as a parameter. This closure is applied to each element of the input collection, and the return value of this closure is used to return a new collection from the collect method.
Something like this should do the trick for you:
def test = [[88,3,2],[22,33,4],[88,3,3]]
def endResult = test.collect { 'test-' + it.join('.') }
println endResult // [test-88.3.2, test-22.33.4, test-88.3.3]
It's worth mentioning that the closure we passed to the collect method uses so-called implicit return - there is no return keyword, but the value it produces from 'test-' + it.join('.') is returned implicitly.

What is the key in complex data type map(object)

I am new to terraform and I am trying to understand the below code snippet.
Variable is of type map(objects) and Its looping over map(objects) and keys function takes a map and returns a list containing the keys from that map. Example: https://www.terraform.io/docs/configuration/functions/keys.html
I believe the output will be something like:
network_ids = {
network_alias = 123
network_alias = 456
network_alias = 789
}
What will be the value for network_alias? I went through many links but I am unable to understand.
code snippet:
locals {
network_ids = {
for network_alias in keys(var.networks) :
network_alias => aws_vpc.subnet[network_alias].id
}
}
variable "networks" {
type = map(object({
network_number = string
availability_zone = string
}))
}
I'm happy to break this down.
So, to begin with, network_ids is a terraform local value. Generally, local values are used to store off computations that you don't want to repeat over and over again.
network_ids is specifically a map for expression. map for expressions are used to build up maps from other, "enumerable" values.
In terraform a map is like a HashMap in other languages (dict in python, Hash in ruby, HashMap in Java and so on). map contains an association list mapping a unique key (always a string) to a value which could be of any, consistent type (meaning you can't have things like { "a" = 4, "b" = "c" } since 4 and "c" have different types).
In your specific example, for network_alias in keys(var.networks) says, basically
loop through the keys (again, strings) in var.networks and bind each one to the name network_alias.
The network_alias => aws_vpc.subnet[network_alias].id part says
build a new map where the key is the same as the keys we're looping over, and the value is a lookup of a subnet's ID indexed by the key.
That all being said, local.network_ids will not end up looking like the following, because maps have distinct keys and the comprehension actually evaluates the key value
network_ids = {
network_alias = 123
network_alias = 456
network_alias = 789
}
It's impossible for me to tell you exactly what the value will be because I don't know the value of var.networks nor that of aws_vpc.subnet.

I Need to Make a HashMap Print out words in order of value

This is my code so far, what am I doing wrong? I need to create a HashMap of <Integer,ArrayList<String>> which will map each word of the test data keyed to the length of the word. Then, display the test String and iterate through the keys and display the words ordered by length. I am not entirely sure what I am doing wrong. Should I use an iterator as opposed to a for-each loop, or would that not make much of a difference?
This is my code thus far
HashMap<Integer,String>map = new HashMap<Integer,String>();
// adds values
map.put(2, "The");
map.put(8, "Superbowl");
Instead of an HashMap, you should use a SortedMap: "A Map that further provides a total ordering on its keys" (JDK 1.7 API doc). A TreeMap would do.
A sorted map will return its keys in sorted order. Since your keys are Integer (hence Comparable), their natural ordering is used.
To list the words by increasing length:
SortedMap<Integer, List<String>> wordsByLength; // filled somewhere
// Iterates over entries in increasing key order
Set<Map.Entry<Integer, List<String>> entries = wordsByLength.entrySet();
for ( Map.Entry<Integer, List<String>> entry : entries ) {
int length = entry.getKey();
List<String> words = entry.getValue();
// do what you need to do
}
Since order is not gauranteed in a HashMap you would need to pull out the keys and sort them before using the sorted key list to loop through the values like so:
Map<Integer,String>map = new HashMap<Integer,String>();
map.put(2, "The");
map.put(8, "Superbowl");
List<Integer> keyList = new ArrayList<Integer>(map.keySet());
Collections.sort(keyList);
for (Integer key : keyList) {
System.out.println(map.get(key));
}
However in your use case where words are the same length you would end up overwriting previous entries in the Map which would not be what you want. A better solution would be to store the words in a List and sort them using a Comparator that compared String lengths like this:
List<String> words = new ArrayList<String>();
// Loop through adding words if they don't already exist in the List
// sort the List by word length
Collections.sort(words, new Comparator<String>() {
public int compare(String s1, String s2) {
return Integer.valueOf(s1.length()).compareTo(s2.length());
}
});
//Now loop through sorted List and print words
for (String word : words) {
System.out.println(word);
}

Ordered iteration in map string string

In the Go blog, this is how to print the map in order.
http://blog.golang.org/go-maps-in-action
import "sort"
var m map[int]string
var keys []int
for k := range m {
keys = append(keys, k)
}
sort.Ints(keys)
for _, k := range keys {
fmt.Println("Key:", k, "Value:", m[k])
}
but what if I have the string keys like var m map[string]string
I can't figure out how to print out the string in order(not sorted, in order of string creation in map container)
The example is at my playground http://play.golang.org/p/Tt_CyATTA3
as you can see, it keeps printing the jumbled strings, so I tried map integer values to map[string]string but I still could not figure out how to map each elements of map[string]string.
http://play.golang.org/p/WsluZ3o4qd
Well, the blog mentions that iteration order is randomized:
"...When iterating over a map with a range loop, the iteration order is not specified and is not guaranteed to be the same from one iteration to the next"
The solution is kind of trivial, you have a separate slice with the keys ordered as you need:
"...If you require a stable iteration order you must maintain a separate data structure that specifies that order."
So, to work as you expect, create an extra slice with the correct order and the iterate the result and print in that order.
order := []string{"i", "we", "he", ....}
func String(result map[string]string) string {
for _, v := range order {
if present in result print it,
}
... print all the Non-Defined at the end
return stringValue
}
See it running here: http://play.golang.org/p/GsDLXjJ0-E

Resources