Scala - foreach is not a member of Int - scala

I'm fairly new to Scala and have to write a program which calculates the average of given List of Integers.
However, I always get the error:
foreach is not a member of Int.
Does anybody of you know how to solve this? Here is my code:
var measureResults = List(100, 36, 54, 4, 22, 37, 86, 20, 3000)
var averageResult = getAverage(measureResults)
println(averageResult)
def getAverage(measureResults: List[Int]): Double = {
var entryList = listOfValidElements(measureResults)
var average = entryList(0)
for (element <- average){
average =+ 1
var trueAverage = average/length(entryList)
return trueAverage
}
}

To actually answer the question as asked
However I always get the error: foreach is not a member of Int.
Does anybody of you know how to solve this?
in you code here:
var average = entryList(0)
for (element <- average){
you take the first entry in entryList, which is an Int. You then try to iterate over it, which doesn't make any sense, and causes the error you get
You probably meant something like
var average = 0
for (element <- entryList) {
(and average += element not average += 1)
but as others have pointed out, there are much better ways of calculating this in Scala

A more Scala-ish approach,
def average(list: List[Int]): Double = {
list.sum.toDouble / list.size
}
Note there is no return statement, the last expression is returned; and no mutability is involved. Casting the sum to Double ensures a floating-point division and result. The method name omits get prefix for conciseness and eventually to convey with a non-getter class method.
From these notes, var measureResults = List(1,2,3) may become immutable, val measureResults = List(1,2,3).

Related

Scala add element to Nil list in scala

I'm solving a problem on leetcode-
https://leetcode.com/problems/minimum-absolute-difference/
I can't seem to understand why in the code below the result list is not correctly appended after resetting it to nil.
I looked online of course but could not fathom the concept behind this behavior. Can someone explain why after result is assigned Nil, no value can get added to that list? How do I reset the list?
I tried with ListBuffer and clear() but I got the same issue, at the end of the run the result is Nil
Expected behavior:
Input: arr = [4,2,1,3]
Output: [[1,2],[2,3],[3,4]]
Actual behavior:
Input: arr = [4,2,1,3]
Output: List()
def minimumAbsDifference(arr: Array[Int]): List[List[Int]] = {
val sortedInput = arr.sorted
var min = Integer.MAX_VALUE
var result = Seq[List[Int]]()
for(i <- 0 until sortedInput.length - 1){
val diff = sortedInput(i+1) - sortedInput(i)
if(min > diff){
result = Nil
min = diff
}
if(min == diff){
result :+ List(sortedInput(i),sortedInput(i+1))
}
}
result.toList
}
You're assigning Nil to result and then never assigning anything else.
Because List is immutable result :+ List(...) returns a new list which is then thrown away. You need to assign the new list to result.
A couple of other notes:
It is extremely inefficient (decidedly not "leet") to append to a list. It's much more efficient to prepend (building the result in reverse) and then reverse at the end.
It is also extremely inefficient to access List items by index.
Use of var should generally be avoided in Scala, though this particular usage (contained locally to an otherwise pure function) is not beyond the pale.

Not sure where this type error is coming from

Im trying to test my code and all I get is a type error. I'm new to scala but as far as I can tell the ide is pointing at a bracket.
I've taken my function out of a main function (not sure what the purpose of that is, new to object oriented programming.) and I've tooled arount with my declarations
class FirstObject {
def computeShippingCosts(weight: Double): Double = {
var init: Double = 5.0
var overW: Double = weight - 30.0
if (weight >= 30) {
var total: Double = init + (overW * .25)
} else {
var total: Double = 5.0
}
}
println(computeShippingCosts(31.0))
}
I would expect the result of the println to be 5.25 but nothing prints other than the error so I don't know what to do.
Firstly, don't use return in Scala, it can cause some very odd errors. The last value in the function will be the result so there is no need for return.
You are getting an error because the last value is val ... and a declaration does not return a value (or rather it has the value Unit, which is the Scala equivalent of void).
It is also a good idea to avoid if/else if there is a function that can do the same thing. In this case you can use max:
def computeShippingCosts(weight: Double): Double =
math.max(5, weight*.25 - 2.5)
I think this also expresses the logic better because it makes it clear that there is a computed cost with a minimum value. And this ensures that a heavier parcel is never cheaper than a lighter parcel, which is harder to guarantee with the original logic.
If you want to retain the original form of code, it looks like this:
def computeShippingCosts(weight: Double): Double = {
val init: Double = 5
val overW: Double = weight - 30.0
if (weight >= 30) {
init + (overW*.25)
} else {
5.0
}
}
Andrey gives an alternative version which is more meaningful if you view the calculation as a base cost with a excess for overweight items:
def computeShippingCosts(weight: Double): Double =
5 + 0.25*(weight - 30).max(0)

Adding key-value pairs to Map in scala

I am very new to scala, and want to create a hash map with the key being a candidate, and value being number of votes. Something like this: {(1:20),(2:4),(3:42),..}.
I`ve attempted with the following code:
val voteTypeList = textFile.map(x=>x(2)) //String array containing votes: [3,4,2,3,2,1,1,1,9,..]
var voteCount:Map[String,Int] = Map()
voteTypeList.foreach{x=>{
if (voteCount.contains(x)){ //Increment value
var i: Integer = voteCount(x)
voteCount.updated(x, i+1)
// print(voteCount(x))
}
else{ //Create new key-value pair
// println(x)
voteCount += (x -> 1)
}}}
print(voteCount.size)
But the voteCount does not get created and .size returns 0.
Thank you!
The problem you're encountering is caused by using a var to hold an immutable Map. Change that to a val holding a mutable Map and it works.
val voteCount:collection.mutable.Map[String,Int] = collection.mutable.Map()
Having said that, there are a number of other issues with the code that makes it non-idiomatic to the Scala way of doing things.
What you really want is something closer to this.
val voteCount = voteTypeList.groupBy(identity).mapValues(_.length)
Jwvh's answer is idiomatic but non-obvious and, if the list has very large numbers of duplicates, memory-heavy.
You might also consider the literal-minded (yet still Scalarific) way of doing this:
val voteCount = voteTypeList.foldLeft(Map(): Map[Int, Int]) { (v, x) =>
v + (x -> (v.getOrElse(x, 0) + 1))
}

Why is my function returning a Unit instead of Int?

I am new to Scala and working on a project. I am writing a function that is suppose to return the smallest Int in an array. However when I run it I get a type error that it is returning unit instead of int.
Here is my code:
def minWhile(r: Array[Int]): Int = {
var pos = 1
var minInt = r(0)
while (pos < r.length) {
if (r(pos) < minInt)
minInt = r(pos)
pos += 1
}
minInt
}
Thank you very much!
Your code is compiled correctly, because it always returns correct type Int. But it may cause some runtime exceptions, if we passed empty array into your function: minWhile(Array()).
def minWhile(r: Array[Int]): Int =
{
var pos = 1
var minInt = r(0) /* potential runtime exception */
while( pos < r.length){
if(r(pos) < minInt)
minInt = r(pos)
pos+=1
}
minInt
}
You have to check arrays bounds working with it.
Or you can use a shorter way:
def minWhile(r: Array[Int]): Option[Int] = if (r.nonEmpty) Some(r.min) else None
Your code should be compiled correctly but it may rise an exception when passed empty container. You are using variables which is discouraged.
I would do it using some recursion calls or scala collections API like so:
array.reduceLeft(a: Somehitng, b: Something => Something)
Check thia link:
http://m.alvinalexander.com/scala/scala-use-reduceleft-get-max-min-from-collection
Consider this more functional style of conveying the semantics of minWhile, as follows,
def minWhile(r: Array[Int]): Int = {
(r zip r.drop(1)).takeWhile(t => t._1 > t._2).last._2
}
where we zip consecutive items and take those monotonically decreasing. The desired result is found in the second part of the last duple.

how do I increment an integer variable I passed into a function in Scala?

I declared a variable outside the function like this:
var s: Int = 0
passed it such as this:
def function(s: Int): Boolean={
s += 1
return true
}
but the error lines wont go away under the "s +=" for the life of me. I tried everything. I am new to Scala btw.
First of all, I will repeat my words of caution: solution below is both obscure and inefficient, if it possible try to stick with values.
implicit class MutableInt(var value: Int) {
def inc() = { value+=1 }
}
def function(s: MutableInt): Boolean={
s.inc() // parentheses here to denote that method has side effects
return true
}
And here is code in action:
scala> val x: MutableInt = 0
x: MutableInt = MutableInt#44e70ff
scala> function(x)
res0: Boolean = true
scala> x.value
res1: Int = 1
If you just want continuously increasing integers, you can use a Stream.
val numberStream = Stream.iterate(0)(_ + 1).iterator
That creates an iterator over a never-ending stream of number, starting at zero. Then, to get the next number, call
val number: Int = numberStream.next
I have also just started using Scala this was my work around.
var s: Int = 0
def function(s: Int): Boolean={
var newS = s
newS = newS + 1
s = newS
return true
}
From What i read you are not passing the same "s" into your function as is in the rest of the code. I am sure there is a even better way but this is working for me.
You don't.
A var is a name that refers to a reference which might be changed. When you call a function, you pass the reference itself, and a new name gets bound to it.
So, to change what reference the name points to, you need a reference to whatever contains the name. If it is an object, that's easy enough. If it is a local variable, then it is not possible.
See also call by reference, though I don't think this question is a true duplicate.
If you just want to increment a variable starting with 3
val nextId = { var i = 3; () => { i += 1; i } }
then invoke it:
nextId()