Clearing up confusion with Maps/Collections (Groov

2019-09-03 08:20发布

问题:

I define a collection that is supposed to map two parts of a line in a tab-separated text file:

def fileMatches = [:].withDefault{[]}

new File('C:\\BRUCE\\ForensicAll.txt').eachLine { line ->
def (source, matches) = line.split (/\t/)[0, 2]
fileMatches[source] << (matches as int)}

I end up with entries such as filename:[984, 984] and I want [filename : 984] . I don't understand how fileMatches[source] << (matches as int) works. How might I get the kind of collection I need?

回答1:

I'm not quite sure I understand what you are trying to do. How, for example, would you handle a line where the two values are different instead of the same (which seems to be what is implied by your code)? A map requires unique keys, so you can't use filename as a key if it has multiple values.

That said, you could get the result you want with the data implied by your result using:

def fileMatches = [:]
new File('C:\\BRUCE\ForensicAll.txt').eachLine { line ->
    def (source, matches) = line.split(/\t/)[0,2]
    fileMatches[source] = (matches as int)
}

But this will clobber the data (i.e., you will always end up with the second value from the last line your file. If that's not what you want you may want to rethink your data structure here.

Alternatively, assuming you want unique values, you could do:

def fileMatches = [:].withDefault([] as Set)
new File('C:\\BRUCE\ForensicAll.txt').eachLine { line ->
    def (source, matches) = line.split(/\t/)[0,2]
    fileMatches[source] << (matches[1] as int)
}

This will result in something like [filename:[984]] for the example data and, e.g., [filename:[984, 987]] for files having those two values in the two columns you are checking.

Again, it really depends on what you are trying to capture. If you could provide more detail on what you are trying to accomplish, your question may become answerable...