简体   繁体   English

Groovy方法构建 <String, List<List> &gt;来自字符串数组的令牌

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

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_Test1INV-Error_Test2 )的HasMap<String, List<List>> ,其值分别为发票行:

[
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: 这是将字符串数组转换为<String, List<List>>标记的方法:

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). 我正在使用许多传统的for循环,并且想知道是否可以进一步简化(使用闭包或任何其他方式)。

UPDATE1: I am trying to print the invoice details per INVOICE_NUMBER as below UPDATE1:我正在尝试按以下方式按每个INVOICE_NUMBER打印发票详细信息

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 UPDATE2:我正在尝试使用invoiceErrors更新Map<String,List<Map<String,String>>> invoices ,如下所示

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.put('error',['INV-Error_Test1' : File Error:该文件格式不受支持])否则,错误消息应附加到匹配的INVOICE和行号上,如下所示

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 该代码看起来不像Groovy,并且大多使用传统的Java代码,想知道是否可以使用Groovy方法简化代码

What you are after is groupBy 你所追求的是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 aa Map<String,List<Map<String,String>>> . 现在这是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: each迭代列表, it有一个映射:

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")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM