groovy map operation not giving expected value - groovy

I am trying to find duplicate tags in an xml file. and i wrote the following:
def xml = new XmlSlurper(false,false).parse('myfile.xml')
List<String> intNames = xml.depthFirst().findAll {
it.name() == 'InternalName'
}
println "Total:" + intNames.size()
// println "Unique:" + intNames.unique().size()
def map = [:]
for(itm in intNames){
if(map.get(itm) == null)
map.put(itm, 1)
else{
def val = map.get(itm)
map.put(itm, val + 1)
println itm
}
}
println "map size: ${map.size()}"
The result shows as:
Total:13811
map size: 13811
if i uncomment the line
// println "Unique:" + intNames.unique().size()
then it looks like
Total:13811
Unique:13792
map size: 13792
So, if unique has less number of values then why else clause is not able to print anything?

Related

How to nested loop in Groovy and get desired final output

I want to get the desired output from the below logic. The output should be a key-value pair.
I'm looping the apiList and appending the apiList <value> to input details <key>. If input details contains v1, the key is appended as (success_api.tenantId.host.v1:http):
class azureConfig {
public static void main(String[] args){
String inputDetails = """version=v1 host=http port=80"""
def inputList = inputDetails.split("\\s")
def id= "tenantId"
def apiList = [{api = success_api}, {api = fail_api}]
def keyValue = ""
for(String item: inputList){
def path = item.split("=")
keyValue += id + "." + path[0] + "::" + path[1] + "\n"
}
println(keyValue)
}
}
Output should be:
success_api.tenantId.host.v1::http
success_api.tenantId.port.v1::80
fail_api.tenantId.host.v1::http
fail_api.tenantId.port.v1::80
I have got this ouput for above logic:
tenantId.version::v1
tenantId.host::http
tenantId.port::80

Groovy convert sql.eachRow results to List

def List_Sftp = sql.eachRow(SftpQuery){ row ->
if(row[4]=="SFTP") {
def names= row.collect{ "${row[0]},${row[1]} ${row[3]} ,${row[4]},${row[5]},${row[6]},${row[7]}" }
println names
}
if(row[4]=="ROSETTANET"){
def names= row.collect{ "${row[0]},${row[1]},${row[2]},${row[4]},${row[5]},${row[6]},${row[7]}" }
println names
}
}
Output above code is
[2.01.00,SAMSUNG,123,XYZ,7C7,file1.xml,zzzz]
[2.01.00,SAMSUNG,123,XYZ,7C7,file2.xml,yyyy]
I can't iterate this out as a list. Suggest how to convert this output to
[2.01.00,SAMSUNG,123,XYZ,7C7,file1.xml,zzzz,2.01.00,SAMSUNG,123,XYZ,7C7,file2.xml,yyyy]
def all = []
sql.eachRow(SftpQuery){ row ->
all.addAll row
}
println all
In all you will have all results in a single iterateble list

How to change variables with in a string into a Map

I have let's say 100 variables in a string , my requirement is to automatically create a Map out of the string:
String str = "$$test$$ $$test2$$ $$test$$ $$test3$$"
Expected Result:
["test":test, "test2":test2, "test3":test3];
EDIT (for dsharew)
This is the last version of my code
def list = queryText.findAll(/\$\$(.*?)\$\$/)
def map = [:]
list.each{
log.debug(it)
it = it.replace("\$\$", "")
log.debug(it)
map.putAt(it, it)
}
log.debug(list)
log.debug(map)
queryText = queryText.replaceAll(/\$\$(.*?)\$\$/) { k -> map[k[1]] ?: k[0] }
log.debug(queryText)
And the logs print the following result:
$$test$$
test
$$test2$$
test2
$$test$$
test
$$test3$$
test3
[$$test$$, $$test2$$, $$test$$, $$test3$$]
{test=test, test2=test2, test3=test3}
test test2 test test3
This should do what you want:
def queryText = "\$\$test\$\$ \$\$test2\$\$ \$\$test\$\$ \$\$test3\$\$"
toMap(queryText.findAll(/\$\$(.*?)\$\$/));
def toMap(list){
def map = [:]
list.each{
it = it.replace("\$\$", "")
map.putAt(it, it)
};
println map;
return map;
}
Following #dsharew answer, I've reduced it a little bit more:
​def queryText = "\$\$test\$\$ \$\$test2\$\$ \$\$test\$\$ \$\$test3\$\$"
def resultMap = queryText
.findAll(/\$\$(.*?)\$\$/)
.collectEntries { String next ->
[next.replace("\$\$", "")] * 2
}
collectEntries can be used to return a map from a collection if it returns a map or a tuple for every entry in the collection.
If you multiply a list by n, you are creating a bigger list with n times its content
BTW cool problem!
This is what I came up with
String str = '$$test$$ $$test2$$ $$test$$ $$test3$$'
str.replaceAll('\\$\\$', '').split(' ').collectEntries { [(it):it] }

Update map using findAll and each in groovy

I would like to update values in map in Groovy filling certain criteria. Here is my code:
def m = [:]
m['a'] = 1
m['b'] = 2
m['d'] = 3
m.findAll { it.value > 1}.each {
it.value = 4
}
println m
But the result is following:
[a:1, b:2, d:3]
Is there any way to do it using both findAll and each? Or I must use
m.each {if (it.value>1) it.value=4}
The root cause is findAll returns a new Map instance.
So you could try:
newMap = m.findAll { it.value > 1}.each {
it.value = 4
}
println m //No change
println newMap //This is what you need!
output is
[a:1, b:2, d:3]
[b:4, d:4]
In each case, the values you are iterating with the each are map entries with a pointer to key and value. When you set it.value you are not replacing what is in the map. You are only updating the pointer in the map entry. To actually set the value, you will need to do the following:
m.findAll { it.value > 1 }.each { m[it.key] = 4 }

How I can find the contents of inner nesting?

Lets say I have a string like this :
string = [+++[>>[--]]]abced
Now I want a someway to return a list that has: [[--],[>>],[+++]]. That is the contents of the deepest [ nesting followed by other nesting. I came up with this solution like this :
def string = "[+++[>>[--]]]"
loop = []
temp = []
string.each {
bool = false
if(it == "["){
temp = []
bool = true
}
else if( it != "]")
temp << it
if(bool)
loop << temp
}
println loop.reverse()
But this indeed takes the abced string after the last ] and put into the result!. But what I want is only [[--],[>>],[+++]]
Are there any groovy way of solving this?
You can use this, if you wouldn't mind using recursion
def sub(s , list){
if(!s.contains('[') && !s.contains('['))
return list
def clipped = s.substring(s.lastIndexOf('[')+1, s.indexOf(']'))
list.add(clipped)
s = s - "[$clipped]"
sub(s , list)
}
Calling
sub('''[+++[>>[--]]]abced''' , [])
returns a list of all subportions enclosed between braces.
['--', '>>', '+++']
If your brackets are symmetrical, you could just introduce a counter variable that holds the depth of the bracket nesting. Only depth levels above 0 are allowed in the output:
def string = "[+++[>>[--]]]abc"
loop = []
temp = []
depth = 0;
string.each {
bool = false
if(it == "["){
temp = []
bool = true
depth++;
}
else if (it == "]"){
depth--;
}
else if (depth > 0){
temp << it
}
if(bool){
loop << temp
}
}
println loop.reverse()
class Main {
private static final def pattern = ~/([^\[]*)\[(.+?)\][^\]]*/
static void main(String[] args) {
def string = "[+++[>>[--]]]abced"
def result = match(string)
println result
}
static def match(String val) {
def matcher = pattern.matcher(val);
if (matcher.matches()) {
return matcher.group(1) ? match(matcher.group(2)) + matcher.group(1) : match(matcher.group(2))
}
[val]
}
}
System.out
[--, >>, +++]
The capturing of the first group in the regex pattern could probably be improved. Right now the first group is any character that is not [ and if there are nothing in front of the first [ then the first group will contain an empty string.

Resources