Método Groovy para construir <cadena, lista <LISTA >> Tokens de la matriz de cadena -- java campo con optimization campo con groovy camp Relacionados El problema

Groovy method to build <String, List<List>> tokens from String array


0
vote

problema

Español

Tengo una matriz de cadenas:

  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,]   

Intenté convertirlo en HasMap<String, List<List>> con la tecla como números de factura ( INV-Error_Test1 , INV-Error_Test2 ) y los valores son cada línea de factura: < / p>

  [ 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]] ]   

y este es el método que convierte la matriz de cadenas en <String, List<List>> TOKENS:

  def extractInvoiceLineItems(def invoices) {     Map invLineItems = new HashMap<String, ArrayList<ArrayList>>();     def lineItems = []     for(int i = 2; i<invoices.length; i++){        def tokens =  invoices[i].split('\|') as List        if(tokens.size != 1) {         lineItems.add(tokens)                  }     }      for (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 }   

Estoy usando mucho de los bucles tradicionales y me pregunto si se puede simplificar más (usando cierres o de otra manera).

update1: Estoy tratando de imprimir los detalles de la factura por INVOICE_NUMBER como se muestra a continuación

  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']     }  }   

Pero estoy viendo todos los valores del mapa cuando estoy tratando de imprimir el valor específico. ¿Alguien puede ayudarme?

update2: Estoy tratando de actualizar el Map<String,List<Map<String,String>>> invoices con los facturasErrors como a continuación

  HasMap<String, List<List>>0  

Estoy tratando de lograr el siguiente mapa Si el mensaje de error no tiene un número de línea, debe agregarse en el nivel superior ya que HasMap<String, List<List>>11111/ Error de archivo: el archivo está en un formato no compatible HasMap<String, List<List>>2 De lo contrario, se debe agregar errores a la factura y enumeración correspondientes a continuación

  HasMap<String, List<List>>3  

Escribí el método a continuación para lograr lo anterior

  HasMap<String, List<List>>4  

El código no se parece a Groovy y utilizando el código de Java tradicional en su mayoría, me pregunto si el código se puede simplificar con el enfoque Groovy

Original en ingles

I have a 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 to convert it to HasMap<String, List<List>> with key as invoice numbers(INV-Error_Test1, INV-Error_Test2) and the values are 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 this is the method which converts the string array into <String, List<List>> tokens:

def extractInvoiceLineItems(def invoices) {     Map invLineItems = new HashMap<String, ArrayList<ArrayList>>();     def lineItems = []     for(int i = 2; i<invoices.length; i++){        def tokens =  invoices[i].split('\\|') as List        if(tokens.size != 1) {         lineItems.add(tokens)                  }     }      for (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 am using lots of traditional for loops and am wondering whether it can be simplified further (using closures or any other way).

UPDATE1: I am trying to print the invoice details per INVOICE_NUMBER as 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 am seeing all the map values when am trying to print the specific value. can someone help me out?

UPDATE2: Am trying to update the Map<String,List<Map<String,String>>> invoices with the invoiceErrors as below

InvoiceError // is an entity with below attributes { String errorMessage,   String invoiceNumber     } ErrorMessage                                          invoiceNumber    -------------                                       -------------------      File Error : The file is in an unsupported format   INV-Error_Test1 Line : 1 Invoice does not foot Reported             INV-Error_Test1 Line : 2 MATH ERROR                                 INV-Error_Test1 Line : 3 MATH ERROR                                 INV-Error_Test2 Line : 3 Invoice does not foot Reported             INV-Error_Test2 

Am trying to achieve below map If the error message doesnt have a line number it need to be appended at the top level as invLineItems.put('error',['INV-Error_Test1' :File Error : The file is in an unsupported format]) Otherwise errormessage should be appended to the matching INVOICE and linenumber as below

invLineItems = [INV-Error_Test1:[[LINE:1, INVOICE_DATE:20150301, INVOICE_NUMBER:INV-Error_Test1, INVOICE_TOTAL:22, error : `Line : 1 Invoice does 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 does not foot Reported`],                                  [LINE:4, INVOICE_DATE:20150301, INVOICE_NUMBER:INV-Error_Test2, INVOICE_TOTAL:28,]],                 error : [[INV-Error_Test1:`File Error : The file is in an unsupported format`]] 

I wrote the below method to achieve the above

def regex = "^Line\\s(?:(\\d+)\\s)?\\s*:\\s+(\\d+)?.+"; for (e in invLineItems ){   def errors =  lipErrors.findAll{it.invoiceNumber==e.key} // finding the error messages with the invoice number   errors.each{  // fetching the line numbre from error message and finding the matching record the invoice number and 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 look like Groovy and using traditional java code mostly, am wondering whether the code can be simplified with Groovy approach

        
     
     

Lista de respuestas

3
 
vote
vote
La mejor respuesta
 

Lo que buscas es range9

Esto debería hacer:

  >>> from random import shuffle >>> >>> r = range(7) >>> shuffle(r) >>> r [5, 3, 6, 4, 1, 0, 2] 0  

editar

Versión que imprime todas las líneas para un cierto número de factura:

  >>> from random import shuffle >>> >>> r = range(7) >>> shuffle(r) >>> r [5, 3, 6, 4, 1, 0, 2] 1  

Esto ahora es un >>> from random import shuffle >>> >>> r = range(7) >>> shuffle(r) >>> r [5, 3, 6, 4, 1, 0, 2] 2 . Así que conseguir un elemento te da la lista. El >>> from random import shuffle >>> >>> r = range(7) >>> shuffle(r) >>> r [5, 3, 6, 4, 1, 0, 2] 3 isa la lista y >>> from random import shuffle >>> >>> r = range(7) >>> shuffle(r) >>> r [5, 3, 6, 4, 1, 0, 2] 4 Hay un mapa:

  >>> from random import shuffle >>> >>> r = range(7) >>> shuffle(r) >>> r [5, 3, 6, 4, 1, 0, 2] 5  

o rápido sucio:

  >>> from random import shuffle >>> >>> r = range(7) >>> shuffle(r) >>> r [5, 3, 6, 4, 1, 0, 2] 6  
 

What you are after is 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,']  // get all "valid" lines def lines = invoices*.split('\\|').findAll{ it.size()>1 } // remember the keys (headline) for later (optional) def heads = lines.first()  // as 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 just as you had it (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 that prints all the lines for a certain invoice number:

def invLineItems = lines.tail().collect{ [heads, it].transpose().collectEntries() }.groupBy{ it.INVOICE_NUMBER } 

This now is a a Map<String,List<Map<String,String>>>. So getting one element gives you the list. The each iterates the list and it there is a 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 an dirty:

print invLineItems.get('INV-Error_Test2')*.collect{ k, v -> [k,"=",v].join(" ") }*.join(", ").join("\n") 
 
 
         
         

Relacionados problema

9  Groovy + OSGI o GRILS?  ( Groovy osgi or grails ) 
He estado aprendiendo OSGI y también un poco sobre Groovy recientemente, pero soy muy nuevo en ambos. Sé que Groovy es parte del marco de grieles y que Griele...

5  Parámetros de cierre groovy  ( Groovy closure parameters ) 
El siguiente ejemplo de usar el método de SendMail proporcionado por el complemento de correo de Grails aparece en este libro . sendMail { to "foo@exa...

0  Groovy Script / Código Java para obtener usuarios distintos de resultados  ( Groovy script java code to get distinct users from resultset ) 
HI I Ejecute una simple consulta de selección en Oracle sobre una mesa y obtenga un conjunto de resultados. como select username, responsibility, project fro...

1  Obtener valor en grieles  ( Get value in grails ) 
def bid= Book.findAllBy(params.bname) println(bid.id) obtuve el resultado [58] ¿Cómo puedo obtener el valor sin la cita? ¿Y cómo puedo convertir '...

1  MD5 y sal  ( Md5 and salt ) 
grieles 1.1 En adelante tiene 'EncodeasMD5' disponible en cadenas: ¿hay una manera de proporcionar una sal para la función? Uso típico: ${myString.encode...

1  Importación de GPARes apropiados  ( Appropriate gpars import ) 
¿Es apropiado usar solo la siguiente importación? import groovyx.gpars.* para que pueda hacer: import groovyx.gpars.* GParsPool.withPool { list ...

0  Obteniendo más información del validador de SAX  ( Getting more informations from sax validator ) 
¿Puedo obtener, por ejemplo, la estructura del nodo o algo así del validador? Algo así como un oyente o un manejador. La excepción no es suficiente. Tengo que...

10  Cómo inspeccionar los objetos mientras se depura Groovy (complemento Eclipse u otro)  ( How to inspect objects while debugging groovy eclipse plugin or other ) 
He comenzado a aprender Groovy construyendo un proyecto de mascotas. Obtengo un poco de HTML con XMLSlurper y lo analice, etc. Estoy usando Eclipse3.4 con Gro...

11  Asignar "IT" en cada iteración (Groovy)  ( Assign it in each iteration groovy ) 
Oye, trato de recortar cada cadena de una lista de una lista en Groovy list.each() { it = it.trim(); } Pero esto solo funciona dentro del cierre, en la...

28  ¿Cómo borrar el índice de elasticsearch?  ( How to erase elasticsearch index ) 
My unidad / prueba de integración incluye pruebas para la funcionalidad de búsqueda. Mi idea es tener un índice de búsqueda vacío antes de cada prueba. Po...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos