Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the grooviest way to get the average of integers from a file?

Tags:

groovy

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}"
like image 408
AbuMariam Avatar asked Aug 12 '17 12:08

AbuMariam


2 Answers

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

Mixing with Java 8 Stream API

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.

like image 188
Szymon Stepniak Avatar answered Oct 02 '22 16:10

Szymon Stepniak


Groovier:

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.

Grooviest:

def mean = myFile.mean()

Of course I cheated, and did this beforehand:

File.metaClass.mean {
    delegate.readLines().with { sum{it as Integer} / size() }
}
like image 44
qlown Avatar answered Oct 02 '22 16:10

qlown