Create Map from existing Map in Groovy - groovy

I have a Map
[email:[hus#gmail.com, vin#gmail.com], jobTitle:[SE, SD], isLaptopRequired:[on, on], phone:[9908899876, 7765666543], name:[hus, Vin]]
for which i need to have a another Map like
[hus:[hus#gmail.com,SE,99087665343],vin:[vin#gmail.com,SE,7765666543]]
How can do it in Groovy?

You could do it like:
def map = [email:['hus#gmail.com', 'vin#gmail.com'], jobTitle:['SE', 'SD'], isLaptopRequired:['on', 'on'], phone:['9908899876', '7765666543'], name:['hus', 'Vin']]
def result = [:]
map.name.eachWithIndex { name, idx ->
result << [ (name): map.values()*.getAt( idx ) - name ]
}
assert result == [hus:['hus#gmail.com', 'SE', 'on', '9908899876'], Vin:['vin#gmail.com', 'SD', 'on', '7765666543']]
Or, you could also do:
def result = [map.name,map.findAll { it.key != 'name' }.values().toList().transpose()].transpose().collectEntries()
But this is just less code at the expense of both readability and resource usage ;-)

The most visual solution i have:
def map = [email:['hus#gmail.com', 'vin#gmail.com'], jobTitle:['SE', 'SD'], isLaptopRequired:['on', 'on'], phone:['9908899876', '7765666543'], name:['hus', 'Vin']]
def names = map.name
def emails = map.email
def jobTitles = map.jobTitle
def isLaptopRequireds = map.isLaptopRequired //sorry for the variable name
def phones = map.phone
def result = [:]
for(i in 0..names.size()-1) {
result << [(names[i]): [emails[i], jobTitles[i], isLaptopRequireds[i], phones[i]]]
}
assert result == [hus:['hus#gmail.com', 'SE', 'on', '9908899876'], Vin:['vin#gmail.com', 'SD', 'on', '7765666543']]
}

Related

How to convert post to Json - Django

I'm trying to convert data from a post to Json formed.
But I still haven't had success.
I tried to do in this format
Unfortunately I couldn't think of anything.
Could anyone help?
Post
{'csrfmiddlewaretoken': 'AdbaFrsoWeZTnT07m3VjncmYnYHztaQ214qh8AYH2cI40veXfe0dmfSwkI1o2ma1',
'det[0][CNPJ]': '8768678678678',
'det[0][UF]': 'SP',
'det[0][dhEmi]': '2021-07-13T08:26:30-03:00',
'det[0][nNF]': '8267',
'det[0][xNome]': 'INDÚSTRIA',
'prod[0][0][CFOP]': '6102',
'prod[0][0][NCM]': '84384000',
'prod[0][0][UF]': 'SP',
'prod[0][0][aliquotaInterna]': '18',
'prod[0][0][counter]': '1',
'prod[0][0][mva]': '34',
'prod[0][0][tributacaoEstadual]': '7',
'prod[0][0][vICMSST]': '0',
'prod[0][0][vICMS]': '25.74',
'prod[0][0][vIPI]': '0',
'prod[0][0][vProd]': '367.68',
'prod[0][0][xProd]': 'FUSO',
'prod[0][1][CFOP]': '6102',
'prod[0][1][NCM]': '84384000',
'prod[0][1][UF]': 'SP',
'prod[0][1][aliquotaInterna]': '18',
'prod[0][1][counter]': '2',
'prod[0][1][mva]': '23',
'prod[0][1][tributacaoEstadual]': '7',
'prod[0][1][vICMSST]': '0',
'prod[0][1][vICMS]': '15.96',
'prod[0][1][vIPI]': '0',
'prod[0][1][vProd]': '228.07',
'prod[0][1][xProd]': 'PORCA',
'xNome': 'COMERCIAL'}
View
if post:
import re
pattDet = re.compile('^([a-zA-Z_]\w+.)\[([0-9_\-][\w\-]*)\]\[([a-zA-Z_\-][\w\-]*)\]$')
pattProd = re.compile('^([a-zA-Z_]\w+.)\[([0-9_\-][\w\-]*)\]\[([0-9_\-][\w\-]*)\]\[([a-zA-Z_\-][\w\-]*)\]$')
pprint.pprint(post)
det = []
prodtem = []
count = 0
for post_name, value in post.items():
try:
det_count = int(pattDet.match(post_name).group(2))
if pattDet.match(post_name).group(1) == 'det':
det[pattDet.match(post_name).group(3)] = value
except:
pass
try:
if pattProd.match(post_name).group(1) == 'prod':
if count == int(pattProd.match(post_name).group(3)):
prodtem.insert(count, {pattProd.match(post_name).group(4): value})
else:
count += 1
except Exception as e:
print(e)
pass
result.append({
'det': det,
'prod': prodtem
})
many month ago i have create this for django rest framwork, a parser mutli dimensional, source is here
i have adapted the parser for you
import re
class ParserMultiDimensional:
_reg_split = re.compile(r"(\[.*?\])")
REG_NAME = r"\s*[a-zA-Z_]\w*\s*"
_reg_name = re.compile(r"^" + REG_NAME + r"$")
REG_INDEX_LIST = r"\s*(\d+)?\s*"
_reg_index_list = re.compile(r"^\[(" + REG_INDEX_LIST + r")\]$") # can be number or nothing
_reg_index_object = re.compile(r"^\[(" + REG_NAME + r")\]$") # need to start with char + alpaha
_reg_list = re.compile(r"^\[" + REG_INDEX_LIST + r"]$")
_reg_object = re.compile(r"^\[" + REG_NAME + r"]$")
def __init__(self, data):
self.data = data
self._valid = None
def conv_list_index(self, key):
ret = self._reg_index_list.search(key).groups()[0]
if not ret:
return -1
return int(ret)
def conv_object_index(self, key):
return self._reg_index_object.search(key).groups()[0]
def conv_index(self, index):
if self.is_list(index):
return self.conv_list_index(index)
elif self.is_object(index):
return self.conv_object_index(index)
else:
return index
def is_list(self, key):
if not key or self._reg_list.match(key):
return True
return False
def is_object(self, key):
if self._reg_object.match(key):
return True
return False
def is_name(self, key):
if self._reg_name.match(key):
return True
return False
def split_key(self, key):
# remove space
key = key.replace(" ", "")
results = self._reg_split.split(key)
# remove empty string
return list(filter(None, results))
def valid_key(self, key):
results = self.split_key(key)
# not result or check first element
if not results or not self.is_name(results[0]):
return []
for r in results[1:]:
if not self.is_list(r) and not self.is_object(r):
return []
return results
def set_type(self, dtc, key, value):
index = self.conv_index(key)
if self.is_list(key):
if not len(dtc) or index == len(dtc):
dtc.append(value)
key = len(dtc) - 1
elif index not in dtc:
# TODO dict same as list
dtc[index] = value
return index
def construct(self, data):
dictionary = {}
for key, value in data.items():
keys = self.valid_key(key)
if not keys:
raise Exception(f"invalid key {keys}")
tmp = dictionary
for curr, nxt in zip(keys, keys[1:]):
set_type = [] if self.is_list(nxt) else {}
tmp = tmp[self.set_type(tmp, curr, set_type)]
self.set_type(tmp, keys[-1], data.get(key))
self.__validate_data = dictionary
def is_valid(self):
self._valid = False
try:
self.construct(self.data)
self._valid = True
except Exception as err:
self.errors = err
return self._valid
#property
def validate_data(self):
if self._valid is None:
raise ValueError("You need to be call is_valid() before access validate_data")
if self._valid is False:
raise ValueError("You can't get validate data")
return self.__validate_data
to use it
parser = ParserMultiDimensional(data_query) # add your post data
if parser.is_valid():
data = parser.validate_data
# do your things
else:
print(parser.errors)
the result with your data is
{
"csrfmiddlewaretoken": "AdbaFrsoWeZTnT07m3VjncmYnYHztaQ214qh8AYH2cI40veXfe0dmfSwkI1o2ma1",
"det": [
{
"CNPJ": "8768678678678",
"UF": "SP",
"dhEmi": "2021-07-13T08:26:30-03:00",
"nNF": "8267",
"xNome": "INDÚSTRIA"
}
],
"prod": [
[
{
"CFOP": "6102",
"NCM": "84384000",
"UF": "SP",
"aliquotaInterna": "18",
"counter": "1",
"mva": "34",
"tributacaoEstadual": "7",
"vICMSST": "0",
"vICMS": "25.74",
"vIPI": "0",
"vProd": "367.68",
"xProd": "FUSO"
},
{
"CFOP": "6102",
"NCM": "84384000",
"UF": "SP",
"aliquotaInterna": "18",
"counter": "2",
"mva": "23",
"tributacaoEstadual": "7",
"vICMSST": "0",
"vICMS": "15.96",
"vIPI": "0",
"vProd": "228.07",
"xProd": "PORCA"
}
]
],
"xNome": "COMERCIAL"
}
have fun with it ! ;)

Groovy create list of 2 maps from string

Hi i have this String which contains List of 2 strings. These 2 strings then contain 2 maps.
Example def listStr = '["{"isReal":true,"area":"a"}","{"isRefundable":false,"area":"b"}"]';
How can i get from this string list of 2 maps?
Result [{isReal=true},{isRefundable=false}]
JsonSlurper can do the job for you:
import groovy.json.JsonSlurper
JsonSlurper js = new JsonSlurper()
def listStr = '["{"isReal":true}","{"isRefundable":false}"]'
def res = []
listStr.eachMatch( /"(\{[^\{\}]+\})"/ ){ res << js.parseText( it[ 1 ] ) }
assert [[isReal:true], [isRefundable:false]] == res
If you want to have a map in the output, you can trasnform the res like:
Map map = res.collectEntries{ it }
assert [isReal:true, isRefundable:false] == map

getting from list without duplicates (Groovy)

I have the following list and code
def myList = [[id:8100-04, name:AAA, code:2281],
[id:8100-05, name:BBB, code:2102],
[id:8100-06, name:CCC, code:6089],
[id:8100-07, name:CCC, code:6089],
[id:8100-08, name:CCC, code:6089]]
//list is retrived but looks something like the above
def newList = myList.findAll {
(it.get("Name").equals("AAA") ||
it.get("Name").equals("BBB") ||
it.get("Name").equals("AFBO") ||
it.get("Name").equals("CCC")) }
def filteredListData = newList.collect { getListData(it.get("Id"), it.get("Name"),
it.get("Code")) }
I want to retrieve all of my newList and if there is a duplicate then retrieve the entry with the lowest id Index.
so from myList i am looking for the result to be:
[[id:8100-04, name:AAA, code:2281],
[id:8100-05, name:BBB, code:2102],
[id:8100-06, name:CCC, code:6089]]
You are almost there.
def myList = [
[id:"8100-04", name:"AAA", code:2281],
[id:"8100-05", name:"BBB", code:2102],
[id:"8100-06", name:"CCC", code:6089],
[id:"8100-07", name:"CCC", code:6089],
[id:"8100-08", name:"CCC", code:6089]
]
def newList = myList.findAll {
it.name in ["AAA", "BBB", "AFBO", "CCC"]
}
def map = [:]
newList.each{
if(!map.get(it.name))
map.put(it.name, it)
}
println map*.value
Output:
[
[id:8100-04, name:AAA, code:2281],
[id:8100-05, name:BBB, code:2102],
[id:8100-06, name:CCC, code:6089]
]
Here is the script which addresses:
Unsorted items, note that order is changed in myList below.
OP did not mention the criteria for duplicate. This considers duplicate based on name and code
def myList = [[id:'8100-07', name:'CCC', code:6089],
[id:'8100-04', name:'AAA', code:2281],
[id:'8100-05', name:'BBB', code:2102],
[id:'8100-06', name:'CCC', code:6089],
[id:'8100-08', name:'CCC', code:6089]]
def newList = myList.findAll {
it.get("name").equals("AAA") ||
it.get("name").equals("BBB") ||
it.get("name").equals("AFBO") ||
it.get("name").equals("CCC")
}
//Sort by order id, name and code fields
def criteria = { a,b -> a.id <=> b.id ?: a.name <=> b.name ?: a.code?: b.code }
//Group by name and code ; apply sort; get the first item; apply sort on final result
def result = newList.groupBy({it.name}, {it.code}).inject([]){li, k, v-> v.collect {key, value -> li << value.sort(criteria)[0]}; li}.sort(criteria)
println result
You can quickly try online Demo
Here is a more "functional style" solution. We group by name, this gives a list for each name. Then we sort each of these lists and take its first element.
def myList = [[id:'8100-04', name:'AAA', code:2281],
[id:'8100-05', name:'BBB', code:2102],
[id:'8100-07', name:'CCC', code:6089],
[id:'8100-06', name:'CCC', code:6089],
[id:'8100-08', name:'CCC', code:6089]]
def newList = myList.findAll {
it.name in ["AAA", "BBB", "AFBO", "CCC"]
}
def groups = newList.groupBy {it -> it.name}
def lowestIds = groups.collect({it.value.sort{it.id}[0]})
println lowestIds
Even simpler:
newList.sort{it.id}.unique{it.name}
println newList

Two lists - Append and exchange

I have this
def url = "http://myurl/".toURL().text
def root = new XmlSlurper().parseText(url)
def namn = root.data.'content-item'.'**'.findAll{ node-> node.name() == 'resourceURI' }*.text()
def mylist = []
namn.each{
mylist << it
}
println mylist
def namn2 = root.data.'content-item'.'**'.findAll{ node-> node.name() == 'relativePath' }*.text()
def mylist2 = []
namn2.each{
mylist2 << it
}
println mylist2
That will be the output of this:
[http://myurl/, http://myurl/]
[/Sixten/1.1.0.235/, /Sixten/1.1.0.331/]
I know want to Exchange it to be
[Sixten-1.1.0.235.nupkg, Sixten-1.1.0.331.nupkg]
and then appended to the first list so it would result like this
[http://myurl/Sixten-1.1.0.235.nupkg, http://myurl/Sixten-1.1.0.331.nupkg]
HOW?
You don't need to do the each to get the values into a list... You already have lists:
def myList = root.data.'content-item'
.'**'
.findAll{ node-> node.name() == 'resourceURI' }
*.text()
def myList2 = root.data.'content-item'
.'**'
.findAll{ node-> node.name() == 'relativePath' }
*.text()
Then, to manipulate myList2, you just need:
myList2 = myList2*.getAt(1..-2)*.replaceAll('/', '-')*.plus('.nupkg')
And to append the urls to the start just requires:
[myList,myList2].transpose().collect { a, b -> a + b }
How about this:
def myList = ['http://myurl/', 'http://myurl/']
def myList2 = ['/Sixten/1.1.0.235/', '/Sixten/1.1.0.331/']
myList2 = myList2.collect { list2Entry ->
list2Entry[1..-2].replaceAll('/', '-') + '.nupkg'
}
def lst = []
myList.eachWithIndex{ txt, idx ->
lst << txt + myList2[idx]
}
println lst
prints:
[http://myurl/Sixten-1.1.0.235.nupkg, http://myurl/Sixten-1.1.0.331.nupkg]
First, inside the collect the leading and trailing slashes are removed by removing the first and last char of the strings with [1..-2]. Then the slashes in the middle of the strings are replaced by minus with replaceAll and .nupkg is added with string concatenation.
Inside the eachWithIndex every string from myList is concatenated with the string inside myList2 at the same position and the resulting string is added to the newly created list lst.

Groovy pointer to list

As I'm totally new to Groovy I have this problem I don't know how to solve:
I wan't to get a new value from a list, which list is depending of the value of the input string:
Simplified Example:
class NewStringValue
{
def getValue (inpList)
{
def list1 = ["L1V1","L1V2","L1V3"];
def list2 = ["L2V1","L2V2","L2V3","L2V4"];
def worklist = Here is my problem, how do I get Worklist to point to the correct list according to the value in InpList, see calling ex. below?
def i = 0;
def j = worklist.size-1;
while (i<=j)
{
// some code.......
newValue = worklist[i];
}
return newValue;}
Example of calling above
value = getValue("list1")
You can use a map, and look up the values based on the key passed in:
class NewStringValue {
def getValue(inpList) {
def lookup = [
list1: ["L1V1","L1V2","L1V3"],
list2: ["L2V1","L2V2","L2V3","L2V4"]
]
def worklist = lookup[inpList]
def newValue = ''
worklist.each {
newValue += it
}
newValue
}
}
new NewStringValue().getValue('list2')

Resources