I have a file with integers for which I want the average. Below is what I came up with and it works, but was wondering if there was a better (groovier) way..
File myFile = new File("myListOfNumbers.txt")
int total = 0
int count = 0
myFile.eachLine {line->
total = Integer.parseInt(line) + total
count++
}
println "Avg is ${total /count}"
If you are looking for more declarative approach then you could do something like this:
def avg2 = myFile.readLines()
.sum({ it.toInteger() }) / myFile.readLines().size()
The only problem is that this is not very efficient, because here we are calling readLines()
method twice. Of course we could split declaration from this expression to make code more efficient and then we will end up with something like this:
def lines = myFile.readLines()
def avg2 = lines.sum({ it.toInteger() }) / lines.size()
Of course you can always mix Groovy approach with Java 8 approach and use built-in .average()
method from Java Stream API. In this case your code would look similar to this one:
def avg1 = Files.lines(myFile.toPath())
.mapToInt({ s -> s.toInteger() })
.average()
.getAsDouble()
I hope it helps.
def mean = myFile.readLines().with { sum{it as Integer} / size() }
Uses groovyisms such as with
and as
.
Inside the closure passed to with
, one can use sum()
and size()
directly, the target will be the object on which .with
is invoked, in our case the list of lines.
def mean = myFile.mean()
Of course I cheated, and did this beforehand:
File.metaClass.mean {
delegate.readLines().with { sum{it as Integer} / size() }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With