What do empty square brackets after a variable name mean in Groovy? - groovy

I'm fairly new to groovy, looking at some existing code, and I see this:
def timestamp = event.timestamp[]
I don't understand what the empty square brackets are doing on this line. Note that the timestamp being def'd here should receive a long value.
In this code, event is defined somewhere else in our huge code base, so I'm not sure what it is. I thought it was a map, but when I wrote some separate test code using this notation on a map, the square brackets result in an empty value being assigned to timestamp. In the code above, however, the brackets are necessary to get correct (non-null) values.
Some quick Googling didn't help much (hard to search on "[]").
EDIT: Turns out event and event.timestamp are both zero.core.groovysupport.GCAccessor objects, and as the answer below says, the [] must be calling getAt() on these objects and returning a value (in this case, a long).

The square brackets will invoke the underlying getAt(Object) method of that object, so that line is probably invoking that one.
I made a small script:
class A {
def getAt(p) {
println "getAt: $p"
p
}
}
def a = new A()
b = a[]
println b.getClass()
And it returned the value passed as a parameter. In this case, an ArrayList. Maybe that timestamp object has some metaprogramming on it. What does def timestamp contains after running the code?
Also check your groovy version.

Empty list, found this. Somewhat related/possibly helpful question here.

Not at a computer, but that looks like it's calling the method event.timestamp and passing an empty list as a parameter.
The same as:
def timestamp = event.timestamp( [] )

Related

groovy iterate through list of key and value

I have this list:
service_name_status=[a-service=INSTALL, b-service=UPGRADE, C-service=UPGRADE, D-service=INSTALL]
And I need to iterate through this list so the first element will be the value of a parameter called "SERVICE_NAME" and the second element will be the value of a parameter called "HELM_COMMAND",
after asserting those values to the parameters I will run my command that uses those parameters and then continue the next items on the list which should replace the values of the parameters with items 3 and 4 and so on.
So what I am looking for is something like that:
def service_name_status=[a-service=INSTALL, b-service=UPGRADE, C-service=UPGRADE, D-service=INSTALL]
def SERVICE_NAME
def HELM_COMMAND
for(x in service_name_status){
SERVICE_NAME=x(0,2,4,6,8...)
HELM_COMMAND=x(1,3,5,7,9...)
println SERVICE_NAME=$SERVICE_NAME
println HELM_COMMAND=$HELM_COMMAND
}
the output should be:
SERVICE_NAME=a-service
HELM_COMMAND=INSTALL
SERVICE_NAME=b-service
HELM_COMMAND=UPGRADE
SERVICE_NAME=c-service
HELM_COMMAND=UPGRADE
SERVICE_NAME=d-service
HELM_COMMAND=INSTALL
and so on...
I couldn't find anything that takes any other element in groovy, any help will be appreciated.
The collection you want is a Map, not a List.
Take note of the quotes in the map, the values are strings so you need the quotes or it won't work. You may have to change that at the source where your data comes from.
I kept your all caps variable names so you will feel at home, but they are not the convention.
Note the list iteration with .each(key, value)
This will work:
Map service_name_status = ['a-service':'INSTALL', 'b-service':'UPGRADE', 'C-service':'UPGRADE', 'D-service':'INSTALL']
service_name_status.each {SERVICE_NAME, HELM_COMMAND ->
println "SERVICE_NAME=${SERVICE_NAME}"
println "HELM_COMMAND=${HELM_COMMAND}"
}
EDIT:
The following can be used to convert that to a map. Be careful, the replaceAll part is fragile and depends on the data to always look the same.
//assuming you can have it in a string like this
String st = "[a-service=INSTALL, b-service=UPGRADE, C-service=UPGRADE, D-service=INSTALL]"
//this part is dependent on format
String mpStr = st.replaceAll(/\[/, "['")
.replaceAll(/=/, "':'")
.replaceAll(/]/, "']")
.replaceAll(/, /, "', '")
println mpStr
//convert the properly formatted string to a map
Map mp = evaluate(mpStr)
assert mp instanceof java.util.LinkedHashMap

Kotlin method chaining to process strings in a list

I have a list of strings I get as a result of splitting a string. I need to remove the surrounding quotes from the strings in the list. Using method chaining how can I achieve this? I tried the below, but doesn't work.Says type interference failed.
val splitCountries: List<String> = countries.split(",").forEach{it -> it.removeSurrounding("\"")}
forEach doesn't return the value you generate in it, it's really just a replacement for a for loop that performs the given action. What you need here is map:
val splitCountries: List<String> = countries.split(",").map { it.removeSurrounding("\"") }
Also, a single parameter in a lambda is implicitly named it, you only have to name it explicitly if you wish to change that.

Dict key getting overwritten when created in a loop

I'm trying to create individual dictionary entries while looping through some input data. Part of the data is used for the key, while a different part is used as the value associated with that key. I'm running into a problem (due to Python's "everything is an object, and you reference that object" operations method) with this as ever iteration through my loop alters the key set in previous iterations, thus overwriting the previously set value, instead of creating a new dict key and setting it with its own value.
popcount = {}
for oneline of datafile:
if oneline[:3] == "POP":
dat1, dat2, dat3, dat4, dat5, dat6 = online.split(":")
datid = str.join(":", [dat2, dat3])
if datid in popcount:
popcount[datid] += int(dat4)
else:
popcount = { datid : int(dat4) }
This iterates over seven lines of data (datafile is a list containing that information) and should create four separate keys for datid, each with their own value. However, what ends up happening is that only the last value for datid exist in the dictionary when the code is run. That happens to be the one that has duplicates, and they get summed properly (so, at least i know that part of the code works, but the other key entries just are ... gone.
The data is read from a file, is colon (:) separated, and treated like a string even when its numeric (thus the int() call in the if datid in popcount).
What am I missing/doing wrong here? So far I haven't been able to find anything that helps me out on this one (though you folks have answered a lot of other Python questions i've run into, even if you didn't know it). I know why its failing; or, i think i do -- it is because when I update the value of datid the key gets pointed to the new datid value object even though I don't want it to, correct? I just don't know how to fix or work around this behavior. To be honest, its the one thing I dislike about working in Python (hopefully once I grok it, I'll like it better; until then...).
Simply change your last line
popcount = { datid : int(dat4) } # This does not do what you want
This creates a new dict and assignes it to popcount, throwing away your previous data.
What you want to do is add an entry to your dict instead:
popcount[datid] = int(dat4)

Processing Split (server)

I am doing 2player game and when I get informations from server, it's in format "topic;arg1;arg2" so if I am sending positions it's "PlayerPos;x;y".
I then use split method with character ";".
But then... I even tried to write it on screen "PlayerPos" was written right, but it cannot be gained through if.
This is how I send info on server:
server.write("PlayerPos;"+player1.x+";"+player1.y);
And how I accept it on client:
String Get=client.readString();
String [] Getted = split(Get, ';');
fill(0);
text(Get,20,20);
text(Getted[0],20,40);
if(Getted[0]=="PlayerPos"){
text("HERE",20,100);
player1.x=parseInt(Getted[1]);
player1.x=parseInt(Getted[2]);
}
It writes me "PlayerPos;200;200" on screen, even "PlayerPos" under it. But it never writes "HERE" and it never makes it into the if.
Where is my mistake?
Don't use == when comparing String values. Use the equals() function instead:
if(Getted[0].equals("PlayerPos")){
From the Processing reference:
To compare the contents of two Strings, use the equals() method, as in if (a.equals(b)), instead of if (a == b). A String is an Object, so comparing them with the == operator only compares whether both Strings are stored in the same memory location. Using the equals() method will ensure that the actual contents are compared. (The troubleshooting reference has a longer explanation.)

groovy - findAll getting only one value

I'm struggling to find examples of findAll with groovy. I've got a very
simple code snippet that gets the property of a node and outputs it's
value. Except I'm only getting the last value when I'm looping through
a series of properties. Is there something I'm doing wrong here, this
seems really simple.
JcrUtils.getChildNodes("footer").findAll{
selectFooterLabel = it.hasProperty("footerLabel") ? it.getProperty("footerLabel").getString() : ""
}
In my jsp I'm just printing the property:
<%=selectFooterLabel%>
Thanks for the help!
findAll returns a List containing all the items in the original list for which the closure returns a Groovy-true value (boolean true, non-empty string/map/collection, non-null anything else). It looks like you probably wanted collect
def footerLabels = JcrUtils.getChildNodes("footer").collect{
it.hasProperty("footerLabel") ? it.getProperty("footerLabel").getString() : ""
}
which will give you a List of the values returned by the closure. If you then want only the subset of those that are not empty you can use findAll() with no closure parameter, which gives you the subset of values from the list that are themselves Groovy-true
def footerLabels = JcrUtils.getChildNodes("footer").collect{
it.hasProperty("footerLabel") ? it.getProperty("footerLabel").getString() : ""
}.findAll()

Resources