Groovy - Collection only returns a single value - groovy

I've got a small code snippet that loops through a node and grabs all its properties.
I can get this to work if I set one variable to grab the properties values (except it has a weird [] surrounding it). But I don't want redundant code so I'm trying to set multiple properties inside the loop, except all that returns is a single value, it's not looping around all the nodes.
WORKING
String selectNodeLabel = null
selectNodeLabel = JcrUtils.getChildNodes("links").collect{
it.getProperty("label").getString()
}
SINGLE VALUE
String selectNodeLabel = null
String selectNodeMeta = null
String selectNodeFooter= null
String topicNode = null
topicNode = JcrUtils.getChildNodes("links").collect{
selectNodeLabel = it.getProperty("label").getString()
selectNodeMeta = it.getProperty("meta").getString()
selectNodeFooter = it.getProperty("footer").getString()
}
Thanks for any help!

Try:
def nodeList = JcrUtils.getChildNodes("links").collect{
[ selectNodeLabel : it.getProperty("label").getString()
selectNodeMeta : it.getProperty("meta").getString()
selectNodeFooter : it.getProperty("footer").getString() ]
}
Then, nodeList will be a list of Maps, so you could do:
println nodeList*.selectNodeLabel
To print all the selectNodeLabel values for example.
To explain the problems with your code... Collect creates a list of the elements returned by the closure. What your SINGLE VALUE code is doing is overwriting the values in the selectNode... variables, and then setting topicNode to the value returned from the closure for each element in JcrUtils.getChildNodes("links").
For this case, topicNode will contain a List of it.getProperty("footer").getString() (as it is the last line in the Closure

Related

Is there a way to use variables as key in an object to find its value in rust? [duplicate]

This question already has answers here:
Access struct field by variable
(3 answers)
Closed last month.
I am new to rust with a javaScript background and i am stuck with getting a value of a json key dynamically.
In JS if i have an object = { "xyz" : "one" , "jkl" : "two" }; and if i have a variable name = "xyz"; , then i can find the corresponding value of 'xyz' key in the object using object[name] which will give me "one" as a result.
Now i have the exact same flow in rust, where i have
let obj = config.clone(); // because config is struct (only cloning could remove the error)
let name = "xyz"; // A variable which is a key in the object
let result = obj[name];` // result which is giving me "cannot index into a value of type `Configuration`" error
I am aware that creating a dict or hashmap will exponentially reduce the time, but the object i have can contain upto 1000 keys and values or more.
If i can create a hashmap with the object I already have, that would be a relief ( only if i knew ).
I have tried multiple ways by just googling a bunch of stuff
let result = obj[name];
let result = obj.&name];
let result = obj[$name];
let result = obj[&name];
let result = obj.$name;
none of them seems to solve the issue.
Thanks in advance.
Accessing fields of structs dynamically is not possible out of the box. See this earlier question.

Any way to conditionalize variable in jsonencoded data?

Say I have the simplified following snippet to create a task definition as json.
...
task_container_definitions = jsonencode([{
name : var.name,
image : "${var.image}:${var.tag}",
cpu : var.cpu,
memory : var.memory,
}])
...
Say I want to add a variable to optionally create an additional definition so it looks something like this:
variable "another_definition" {
type = any
default = {}
}
...
task_container_definitions = jsonencode([{
name : var.name,
image : "${var.image}:${var.tag}",
cpu : var.cpu,
memory : var.memory,
},
var.another_definition
])
And define it as follows.
another_definition = {
name = "another_container"
image = "another_container"
cpu = 10
memory = 512
essential = true
}
I am able to get this to to output as expected as long as the variable is defined.
...
+ {
+ cpu = 10
+ essential = true
+ image = "another_container"
+ memory = 512
+ name = "another_container"
},
But if the variable is not defined, I see empty {} added to the output when I do a terraform plan, which is not what I expect. I have tried using null as well as the default but get an error.
...
+ {},
Is there a way to toggle this variable off so that if it is not defined then it doesn't show up in the outputted json definition? Is there a better approach than what I am attempting?
I was a little confused at first as to what you were asking, thinking that you were asking for the functionality of the merge function, and I mention that only in case I was right the first time, but I think I now understand your problem as that you want this task_container_definitions to have either one or two elements, depending on whether var.another_definition is set.
There's no single function for that particular situation, but I think we can combine some language features together to get that result.
First, let's decide that the variable being set means that it has a non-null value, and thus its default value should be null to represent the "unset" case:
variable "another_definition" {
type = any
default = null
validation {
# The time constraint above is looser than we really
# want, so this validation rule also enforces that
# the caller can't set this to something inappropriate,
# like a single string or a list.
condition = (
var.another_definition != null ?
can(keys(var.another_definition)) :
true
)
error_message = "Additional task container definition must be an object."
}
}
In Terraform it's a pretty common situation to need to convert between a value that might be null and a list that might have zero or one elements, or vice-versa, and so Terraform has some language features to help with that. In this case we can use a splat expression to concisely represent that. Let's see how that looks in terraform console first just to give a sense of what we're achieving with this:
$ terraform console
> null[*]
[]
> "hello"[*]
[
"hello",
]
> { object = "example" }[*]
[
{
"object" = "example"
},
]
Notice that when I applied the [*] operator to null it returned an empty list, but when I applied it to these other values it converted them to a single-element list. This is how the [*] operator behaves when you apply it to something that isn't a list; see the splat operator docs if you want to learn about the different behavior for lists, which isn't really relevant here because of the validation rule I added above which prevents the var.another_definition value from being a list.
Another tool we have in our Terraform toolbox here is the concat function, which takes one or more lists and returns a single list with the input elements all concatenated together in the given order. We can use this to combine your predefined list that's populated from var.name, var.cpu, etc with the zero-or-one element list created by [*], in order to create a list with their one or two elements:
locals {
task_container_definitions = concat(
[
name = var.name
image = "${var.image}:${var.tag}"
cpu = var.cpu
memory = var.memory
],
var.another_definition[*],
)
task_container_definitions_json = jsonencode(local.task_container_definitions)
}
If any of the arguments to concat are empty lists then they are effectively ignored altogether, because they contribute no elements to the result, and so this achieves (what I hope is) the desired result, by making the "other definition" appear in the result only when it's set to something other than null.

how to define a list of variable number of objects in groovy?

I am learning groovy, I am using the documentation and some youtube videos. I want for testing to find out how to declare an array of objects, but that array will have a x number of objects depending on some stuff. Here is what I tried:
class Issue {
String type = ""
String severity = ""
String linestart = ""
String filename = ""
String meesage = ""
}
def test(){
Issue[] Issues = new Issue[5]
Issues[0].type = "error"
println Issues[0].type
}
test()
what I get:
Caught: java.lang.NullPointerException: Cannot set property 'type' on null object
java.lang.NullPointerException: Cannot set property 'type' on null object
I assume my array does not have 5 Issues objects inside, and that is why is trying to set on null object. How would be the right syntax to do so?
You are right- all the values are initially null. You have to first create instances of Issue and assign it to the array elements,
Issues[0] = new Issue()
Issues[0].type = "error"
alternatively, using "groovy" syntax,
Issues[0] = new Issue(type: "error")

"new Set" is returning an empty set in nodejs

I was testing some websites using the below function with n, suddenly "new Set" started returning empty Array as the following:
function collectAllSameOriginAnchorsDeep(sameOrigin = true) {
const allElements = [];
// Some coding here
const filtered = allElements
// Some coding here
console.log(filtered) // The items are printed in the log probably
return Array.from(new Set(filtered)); // Nothing is getting returned!
}
If I replace the last line with return Array.from(filtered), then it works fine but I'm using "Set" to remove any repeated values.
Because Set receives iterable object as its input parameter, and will create set object respectively. Hence, we can construct a set from an array — but it will only include distinct elements from that array, aka no duplicate.
And of course, we can also convert a set back to array using Array.from() method.
let set = new Set([1,2,3]); // {1,2,3}
let arr = Array.from(set);//[1,2,3]
So you need to convert set back to array , please check here to understand the difference between set and array.
Hope this will help you!

Calling a field name in a Struct in Matlab?

I am passing in a variable name MetabMapString to the function spectroscopy(). MetabMapString is the name of the field I want to call. But It seems as if Matlab is thiking that MetabMapString is the name of the fields cause it returns that there is no field names MetabMapString. I have included some code. Is there a way to get this to work?
function spectroscopy(MetabMapString)
spect = importdata(spectLCMI);
n = length(spect.MetabMapString);
Row = spect.Row;
Col = spect.Col;
spectOrig = spect.MetabMapString;
...
end
Here is the error
??? Reference to non-existent field 'MetabMapString'.
Error in ==> SpectDraw>spectroscopy at 1165
n = length(spect.MetabMapString);
It should be:
n = length(spect.(MetabMapString));
That should work. Same in all other places where you're using a variable which contains a string as a field name of a struct or MATLAB class, or as a method name of a class:
spectOrig = spect.(MetabMapString);

Resources