pulling a list based on the key - groovy

I have a record as
["name1":["value1":10, "value2":name1, "value3":150, "value4":20],
"name2":["value1":10, "value2":name2, "value3":150, "value4":20]]
I have a list where the values are name1, name2, etc.
I want to pull the list depending on the name1 as
["name1":["value1":10, "value2":name1, "value3":150, "value4":20]]
.subMap(["name1"]) did work for me, but I have a list and by looping the list I need to pull the values
Ex : namesList.each{record ->
newMap = firstmap.subMap(record)
}

Use subMap(Collection keys):
def map = ["name1":["value1":10, "value2":"name1", "value3":150, "value4":20],
"name2":["value1":10, "value2":"name2", "value3":150, "value4":20]]
//Answer here, return Map still:
println map.subMap("name1")
//Or
println map.subMap(["name1", "name2"])

Related

Move Dictionary Keys to lis for particular values

I trying to make this code work:
civil_freq= { '430.00': ['aaa'],
'430.02': ['aaa'],
'430.04': ['aaa'],
'430.06': ['bbb'],
'430.08': ['bbb'],
'430.10': ['bbb'],
'430.12': ['none'],
'430.14': ['none']}
person_freq=[]
person = 'bbb'
for key in civil_freq:
if civil_freq[key] == person:
person_freq.append(civil_freq.get(key))
print(person_freq)
it return empty list, but I need smth like
['430.06', '430.08', '430.10']
Issue: You're storing the persons names in a list (within your civil_freq dictionary) but comparing it with a string (variable person). This comparison won't work.
Try this:
person = ["bbb"]
for k, v in civil_freq.items():
if v == person:
person_freq.append(k)
print(person_freq)
or change the values within your dictionary from lists to strings!

How to loop through a map and display only one row if there is matching values

I have a map with differnt keys and multiple values.If there is any matching job among different keys,I have to display only one row and grouping code values.
def data = ['Test1':[[name:'John',dob:'02/20/1970',job:'Testing',code:51],[name:'X',dob:'03/21/1974',job:'QA',code:52]],
'Test2':[name:'Michael',dob:'04/01/1973',job:'Testing',code:52]]
for (Map.Entry<String, List<String>> entry : data.entrySet()) {
String key = entry.getKey();
List<String> values = entry.getValue();
values.eachWithIndex{itr,index->
println("key is:"+key);
println("itr values are:"+itr);
}
}
Expected Result : [job:Testing,code:[51,52]]
First flatten all the relevant maps, so whe just have a flat list of all of them, then basically the same as the others suggested: group by the job and just keep the codes (via the spread operator)
def data = ['Test1':[[name:'John',dob:'02/20/1970',job:'Testing',code:51],[name:'X',dob:'03/21/1974',job:'QA',code:52]], 'Test2':[name:'Michael',dob:'04/01/1973',job:'Testing',code:52]]
assert data.values().flatten().groupBy{it.job}.collectEntries{ [it.key, it.value*.code] } == [Testing: [51, 52], QA: [52]]
Note: the question will be changed according to the comments from the other answers.
Above code will give you the jobs and and their codes.
As of now, it's not clear, what the new expected output should be.
You can use the groovy's collection methods.
First you need to extract the lists, since you dont need the key of the top level element
def jobs = data.values()
Then you can use the groupBy method to group by the key "job"
def groupedJobs = jobs.groupBy { it.job }
The above code will produce the following result with your example
[Testing:[[name:John, dob:02/20/1970, job:Testing, code:51], [name:Michael, dob:04/01/1973, job:Testing, code:52]]]
Now you can get only the codes as values and do appropriate changes to make key as job by the following collect function
def result = groupedJobs.collect {key, value ->
[job: key, code: value.code]
}
The following code (which uses your sample data set):
def data = ['Test1':[name:'John', dob:'02/20/1970', job:'Testing', code:51],
'Test2':[name:'Michael', dob:'04/01/1973', job:'Testing', code:52]]
def matchFor = 'Testing'
def result = [job: matchFor, code: data.findResults { _, m ->
m.job == matchFor ? m.code : null
}]
println result
results in:
~> groovy solution.groovy
[job:Testing, code:[51, 52]]
~>
when run. It uses the groovy Map.findResults method to collect the codes from the matching jobs.

Adding dictionary values to a list?

I have the following:
list_of_values = []
x = { 'key1': 1, 'key2': 2, 'key3': 3 }
How can I iterate through the dictionary and append one of those values into that list? What if I only want to append the value of 'key2'.
If you only want to append a specific set of values you don't need to iterate through the dictionary can simply add it to the list
list_of_values.append(x["key2"])
However, if you insist on iterating through the dictionary you can iterate through the key value pairs:
for key, value in x.items():
if key == "key2":
list_of_values.append(value)
If you really want to iterate over the dictionary I would suggest using list comprehensions and thereby creating a new list and inserting 'key2' :
list_of_values = [x[key] for key in x if key == 'key2']
because that can be easily extended to search for multiple keywords:
keys_to_add = ['key2'] # Add the other keys to that list.
list_of_values = [x[key] for key in x if key in keys_to_add]
That has the simple advantage that you create your result in one step and don't need to append multiple times. After you are finished iterating over the dictionary you can append the list, just to make it interesting, you can do it without append by just adding the new list to the older one:
list_of_values += [x[key] for key in x if key in keys_to_add]
Notice how I add them in-place with += which is exactly equivalent to calling list_of_values.append(...).
list_of_values = []
x = { 'key1': 1, 'key2': 2, 'key3': 3 }
list_of_values.append(x['key2'])

How can I assign a list to another list in Groovy

I want to do something like this in Groovy:
List<MyObject> list1 = getAList();
How can I assign a list to other list in groovy without having to iterate through the list I want to assign?
That will work as you have it (assuming getAList returns a List)...
Or do you mean you want a new list containing the same elements as the list returned?
If that's the case, you can do
List<MyObject> list1 = getAList().collect()
Or
List<MyObject> list1 = new ArrayList<MyObject>( getAList() )
If you only want to concatenate the elements of one array/list with another, you can do the following:
def ar1 = ["one","two"]
def ar2 = ["three","four"]
def ar3 = ar1 + ar2
return ar3
This should produce
["one","two","three","four"]

getting distinct users from the resultset and string concat on other fields

I have a Sql ResultSet from a query. It has following fields: username, department, ..responsibility.
There are repeated username with different values for deptmt and responsblty. I want to get a map/list of unique usernames with a list of departments and responsibilities for each user in the resultset
So if
resultset = (Sam, dept1,.. resp1),
(Tom, dept1,..resp3),
(Sam,dept2,..resp2),
(Tom,dept3,..resp3)...etc
the output should be
finalList = [["Sam", "dept1,dept2", "resp1,resp2"],["Tom", "dept1,dept3", "resp3"]]
Things to note: 1) There may be n columns which are variable (column list read from a property file) so the code to be adaptable. _ not reqired for now, its a fixed list right now
2)All values enclosed in double quotes and seperated by comma.
3) For tom responsibility contains only resp3 since its repeated...i.e unique values in the list.
How do I convert the resultset?
Thanks
A shorter alternative to Bill's solution would be:
def data = [ ['Sam', 'dept1','resp1'],
['Tom', 'dept1','resp3'],
['Sam', 'dept2','resp2'],
['Tom', 'dept2','resp4'] ]
def output = data.groupBy { it[0] }.collect { name, vals ->
$/"$name", "${vals*.getAt( 1 ).join(',')}", "${vals*.getAt( 2 ).join(',')}"/$
}
output.each {
println it
}
Which prints:
"Sam", "dept1,dept2", "resp1,resp2"
"Tom", "dept1,dept2", "resp3,resp4"
This should get you pretty close. Note that the final output doesn't have the quotes in it (Groovy doesn't print those for strings). Looking at the code, you can see that the "output" is a Collection of Lists, each with 3 items: the name, the comma-sep list of department strings, then the comma-sep list of responsibility strings.
BTW, you may want to use something other than comma in the inner-strings, if you want to create a comma-sep list as the final output.
def data = [ ['Sam', 'dept1','resp1'],
['Tom', 'dept1','resp3'],
['Sam', 'dept2','resp2'],
['Tom', 'dept2','resp4'] ]
def tmpmap = [:]
data.each { inputrow ->
def name = inputrow[0]
def curlist = tmpmap[name]
if ( curlist == null ) { // first time seeing this name
curlist = [name,inputrow[1],inputrow[2]]
tmpmap.put( name, curlist );
} else { // seen this name before
curlist[1] += ',' + inputrow[1]
curlist[2] += ',' + inputrow[2]
}
}
output = tmpmap.values()
println output

Resources