java - Groovy method to build <String, List<List>> tokens from String array -
i have string array:
def invoices = [ledes98bi v2, line|invoice_date|invoice_number|invoice_total, 1|20150301|inv-error_test1|22, 2|20150301|inv-error_test1|24, 3|20150301|inv-error_test2|26, 4|20150301|inv-error_test2|28,]
i tried convert hasmap<string, list<list>>
key invoice numbers(inv-error_test1
, inv-error_test2
) , values each invoice line:
[ inv-error_test2:[[3,20150301, inv-error_test2,26], [4,20150301, inv-error_test2,28]], inv-error_test1:[[1,20150301, inv-error_test1,22], [2,20150301, inv-error_test1,24]] ]
and method converts string array <string, list<list>>
tokens:
def extractinvoicelineitems(def invoices) { map invlineitems = new hashmap<string, arraylist<arraylist>>(); def lineitems = [] for(int = 2; i<invoices.length; i++){ def tokens = invoices[i].split('\\|') list if(tokens.size != 1) { lineitems.add(tokens) } } (int i=0; i< lineitems.size; i++) { invnumber = lineitems.get(i).get(1) if(invlineitems.keyset().find{it == invnumber}) { templineitem = invlineitems.get(invnumber) templineitem.add(lineitems.get(i)) invlineitems.put(invnumber,templineitem) } else { def list = [] list.add(lineitems.get(i)) invlineitems.put(invnumber,list) } } invlineitems }
i using lots of traditional loops , wondering whether can simplified further (using closures or other way).
update1: trying print invoice details per invoice_number
below
def lines = invoices*.split('\\|').findall{ it.size()>1 } def heads = lines.first() def invlineitems = lines.tail().collect{ [heads, it].transpose().collectentries() }.groupby{ it.invoice_number } // => [inv-error_test1:[[line:1, invoice_date:20150301, invoice_number:inv-error_test1, invoice_total:22], [line:2, invoice_date:20150301, invoice_number:inv-error_test1, invoice_total:24]], inv-error_test2:[[line:3, invoice_date:20150301, invoice_number:inv-error_test2, invoice_total:26], [line:4, invoice_date:20150301, invoice_number:inv-error_test2, invoice_total:28,]]] println " inv-error_test2 details " invlineitems.get('inv-error_test2').each{ it.each{k,v -> print "line = "+ it['line'] print " "+" invoice_date = "+it['invoice_date'] print " "+" invoice_total = "+it['invoice_total'] } }
but seeing map values when trying print specific value. can me out?
update2: trying update map<string,list<map<string,string>>> invoices
invoiceerrors below
invoiceerror // entity below attributes { string errormessage, string invoicenumber } errormessage invoicenumber ------------- ------------------- file error : file in unsupported format inv-error_test1 line : 1 invoice not foot reported inv-error_test1 line : 2 math error inv-error_test1 line : 3 math error inv-error_test2 line : 3 invoice not foot reported inv-error_test2
am trying achieve below map if error message doesnt have line number need appended @ top level invlineitems.put('error',['inv-error_test1' :
file error : file in unsupported format])
otherwise errormessage should appended matching invoice , linenumber below
invlineitems = [inv-error_test1:[[line:1, invoice_date:20150301, invoice_number:inv-error_test1, invoice_total:22, error : `line : 1 invoice not foot reported`], [line:2, invoice_date:20150301, invoice_number:inv-error_test1, invoice_total:24, error : `line : 2 math error`], inv-error_test2:[[line:3, invoice_date:20150301, invoice_number:inv-error_test2, invoice_total:26, , error : `line : 3 math error | line : 3 invoice not foot reported`], [line:4, invoice_date:20150301, invoice_number:inv-error_test2, invoice_total:28,]], error : [[inv-error_test1:`file error : file in unsupported format`]]
i wrote below method achieve above
def regex = "^line\\s(?:(\\d+)\\s)?\\s*:\\s+(\\d+)?.+"; (e in invlineitems ){ def errors = liperrors.findall{it.invoicenumber==e.key} // finding error messages invoice number errors.each{ // fetching line numbre error message , finding matching record invoice number , line number in invlineitems int linenumber if (it.errormessage.matches(regex)) { pattern p = pattern.compile("\\d+"); matcher m = p.matcher(it.errormessage); if (m.find()) { linenumber = integer.parseint(m.group()); } println "linenumber = "+linenumber } if(e.value['line_item_number'].find{it==linenumber.tostring()}) { def data = liperrors.findall{it.invoicenumber==e.key && it.errormessage.matches("^line\\s+"+linenumber+"?\\:\\s+"+linenumber+"?.+")} e.getvalue().each{it.put("error", data.errormessage.join("|"))} } } }
the code doesnt groovy , using traditional java code mostly, wondering whether code can simplified groovy approach
what after groupby
this should do:
def invoices = [ 'ledes98bi v2', 'line|invoice_date|invoice_number|invoice_total', '1|20150301|inv-error_test1|22', '2|20150301|inv-error_test1|24', '3|20150301|inv-error_test2|26', '4|20150301|inv-error_test2|28,'] // "valid" lines def lines = invoices*.split('\\|').findall{ it.size()>1 } // remember keys (headline) later (optional) def heads = lines.first() // map of maps println lines.tail().collect{ [heads, it].transpose().collectentries() }.groupby{ it.invoice_number } // => [inv-error_test1:[[line:1, invoice_date:20150301, invoice_number:inv-error_test1, invoice_total:22], [line:2, invoice_date:20150301, invoice_number:inv-error_test1, invoice_total:24]], inv-error_test2:[[line:3, invoice_date:20150301, invoice_number:inv-error_test2, invoice_total:26], [line:4, invoice_date:20150301, invoice_number:inv-error_test2, invoice_total:28,]]] // or had (map of string list) println lines.tail().groupby{ it[2] } // => [inv-error_test1:[[1, 20150301, inv-error_test1, 22], [2, 20150301, inv-error_test1, 24]], inv-error_test2:[[3, 20150301, inv-error_test2, 26], [4, 20150301, inv-error_test2, 28,]]]
edit
version prints lines invoice number:
def invlineitems = lines.tail().collect{ [heads, it].transpose().collectentries() }.groupby{ it.invoice_number }
this a map<string,list<map<string,string>>>
. getting 1 element gives list. each
iterates list , it
there map:
invlineitems.get('inv-error_test2').each{ print "line = "+ it['line'] print " "+" invoice_date = "+it['invoice_date'] print " "+" invoice_total = "+it['invoice_total'] println "" }
or quick dirty:
print invlineitems.get('inv-error_test2')*.collect{ k, v -> [k,"=",v].join(" ") }*.join(", ").join("\n")
Comments
Post a Comment