How to access list in Scala test case - scala

I have a test case as a list, and I want to access "Andorra" as input[0] and "04" as input[1] of the list for a parameter, but I am given the error value input of type (String, String) does not take type parameters. How do I properly access these strings and use them for my parameters?
test("normal case") {
val testCases = List {
("Andorra", "04") -> (Map("la massana" -> 7211), List("les escaldes"))
}
for ((input, (mapOut, listOut)) <- testCases) {
var computedMap: collection.mutable.Map[String, Int] = PaleBlueDot.cityPopulations(countriesFile, citiesFilename, input[0], input[1])
var computedList: List[String] = PaleBlueDot.aboveAverageCities(countriesFile, citiesFilename, input[0])
assert(computedMap == mapOut, input + " -> " + computedMap)
assert(computedList.sorted == listOut.sorted, input + " -> " + computedList)
}
}

Related

Hello I am new to Scala, I have a question about an anonymous function problem

How this function returns "hello there"? There is definitely something that I am missing here but I don't see it
def saySomething(prefix: String) = (s: String) => {
prefix + " " + s
}
def saySomethingElse = saySomething("hello")
print(saySomethingElse("there"))
I tried tracing how "hello" is substituted by prefix since its the first string being passed in the function "saySomething" but then I don't understand how "there" is attached to the result.
Any help is appreciated
Breaking it down, it works like this:
def saySomething(prefix: String) = (s: String) => {
prefix + " " + s
}
This is a function called saySomething that returns a value:
def saySomething(prefix: String) = ???
The value it returns is an anonymous function:
(s: String) => { prefix + " " + s }
Each time you call saySomething(prefix: String), a new function is created and the value of prefix is remembered by that new function. So when you call saySomething("hello") it remembers "hello" and returns this.
(s: String) => { "hello" + " " + s }
def saySomethingElse = (s: String) => { "hello" + " " + s }
When you call that new function, you get the final string:
saySomethingElse("there")
// == ((s: String) => { "hello" + " " + s })("there")
// == "hello" + " " + "there"
You could call it with a different value and get a different result:
saySomethingElse("Dolly")
// == ((s: String) => { "hello" + " " + s })("Dolly")
// == "hello" + " " + "Dolly"
Note that saySomethingElse can just be a val not a def. It is just a variable that contains a function, it doesn't need to be a function itself.

Refactor code to return String instead of println

I have this Scala code which prints out all permutations of a string:
def permuteRecursively(perm: String, word: String): Unit ={
if (word.isEmpty) println(perm + word)
else {
for (i <- 0 to word.length -1){
permuteRecursively(
perm + word.charAt(i),
word.substring(0, i) + word.substring(i + 1, word.length)
)
}
}
}
I tried to refactor it so that it would return a String rather than just print the result:
def permuteRecursively(perm: String, word: String): String ={
var result: String = ""
if (word.isEmpty) result = (perm + word)
else {
for (i <- 0 to word.length -1){
permuteRecursively(
perm + word.charAt(i),
word.substring(0, i) + word.substring(i + 1, word.length)
)
}
}
result
}
But it just returns "", likely because the variable is being reset on each recursive stack call. How can I store the state between recursive calls, without using a global variable?
Instead of printing out all the permutations and returning Unit (nothing useful), you now want it to return, not a String, but a collection of Strings.
def permuteRecursively(perm: String, word: String): Seq[String] =
if (word.isEmpty) Seq(perm + word)
else
word.indices.flatMap { i =>
permuteRecursively(
perm + word.charAt(i),
word.substring(0, i) + word.substring(i + 1, word.length)
)
}

passing variable argument data type to a scala method

I want to create a method/function in scala which can take variable arguments of type string or int and return the result of type String or Int.
def Hello(name: String, Param: int*/string*): Int/String= {
var index = 0
while(index < Param.length) {
var n = name
var ar = Param(index)
if ( n.equals(ar) ) return Param(index + 1)
else index = index + 1
}
return Param(index.length -1)
}
If we call the Hello function then it should return the result as given below.
val Res1 = Hello("Jack", "rakesh", 1, "Jack", 2, "No one")
println(Res1)
=> this should return value 2
val Res2 = Hello("ABC", "rakesh", 1, "Jack", 2, "Vik", 3, "ram", 4, "No one")
println(Res2)
=> this should return value "No one"
Using Any should work:
def hello(name: Any, param: Any*): Any= {
var list = param.dropWhile(_ != name)
list.drop(1).headOption.orElse(param.lastOption).getOrElse("")
}
Depending on how type safe you want it to be, you can try to use generics or other means to restrict the types used. Or you can just pattern match the response type:
hello("ABC", "rakesh", 1, "Jack", 2, "Vik", 3, "ram", 4, "No one") match {
case i: Int => println("Got a int:" + i)
case s: String=> println("Got a string:" + s)
}
This will help you
def Hello( name: String,args: Any* ) = {
val index = args.indexOf(name)
if(index == -1)
args(args.length - 1)
else
args(index + 1)
}
Your whole approach is faulty, but here's how it can be done in a type-safe manner.
def Hello(name: String, param: Either[Int,String]*): Either[Int,String] = {
param.sliding(2,2)
.find(_(0).fold(_ => false, _ == name))
.fold(param.last)(_(1))
}
Usage:
Hello("Jack", Right("rakesh"), Left(1), Right("Jack"), Left(2), Right("No one"))
// res0: Either[Int,String] = Left(2)
Hello("ABC", Right("rakesh"), Left(1), Right("Jack"), Left(2),
Right("Vik"), Left(3), Right("ram"), Left(4), Right("No one"))
// res1: Either[Int,String] = Right(No one)
But it would be better to rethink it from the ground up.
I believe, what you want to achieve, is to get an index of a String element(if start counting from 1) in varargs, or return "No one". No need to pass indices to the method. You can do it like this:
def hello(name: String, params: String*): Any = {
val idx = params.indexOf(name)
if (idx != -1) idx + 1 else "No One"
}
Unfortunately both this:
def Hello(name: String, args: Any* ) = {
val index = args.indexOf(name)
if(index == -1)
args(args.length - 1)
else
args(index + 1)
}
and this:
def hello(name: String, param: Any*): Any= {
var index = 0
while(index < param.length) {
var n = name
var ar = param(index)
if ( n.equals(ar) ) return param(index + 1)
else index = index + 1
}
param(index -1)
}
are broken, as they throw an exception if you try to find the index of "No one", as index + 1 will equal to the size of the array. And it's better to compare things in Scala with == for logical equality.
But it's better not to return Any at all, but return Option[Int]:
def hello(name: String, params: String*): Option[Int] =
Option(params.indexOf(name)).filter(_ != -1).map(_ + 1)
So then you can use it like this:
val message1 = hello("Jack", "rakesh" ,"Jack").getOrElse("No one")
val message2 = hello("ABC", "rakesh", "Jack", "Vik", "ram").getOrElse("No one")
Answering the comment:
I want to know how can i pass mixed datatypes to "param".
The simplest way is to have them all of type Any
and also get string or integer as return type
The same way, defining return type as Any
The only small issue here, is that there will be no compile time check against other types. E.g. somebody might pass Boolean or any complex object along with String's and Int's to your function. But you can check at runtime against it or play with types to limit them. I don't know your requirement here, maybe it's even advantage for you.
If having Any is fine, then I would solve it like this:
def Hello(name: Any, params: Any*): Any = Option(params)
.withFilter(_.nonEmpty)
.map(_.indexOf(name))
.filter(i => i != -1 && i < params.length - 1)
.map(i => params(i + 1))
.getOrElse("No one")
Or, if you can assume, params are never empty and you have to use the last param as the default, instead of just hard coded "No one":
def Hello(name: Any, params: Any*): Any = Option(params)
.withFilter(_.nonEmpty)
.map(_.indexOf(name))
.filter(i => i != -1 && i < params.length - 1)
.map(i => params(i + 1))
.getOrElse(params.last)
Notice the check against "No one" attack: i < params.length - 1.
Notice that name now is also of type Any.
Now, even if you pass "No one" as a name, the Option will evaluate to None thanking to the filter, and getOrElse will give you the default "No one" instead of an exception.

Scala anonymous functions

Why does my anonymous function not work?
Compiler shows me an error on line with
foreach((line: String) => {
My code:
Source.fromFile(siteDir.getPath).getLines()
.map(_.trim())
.filter(!_.isEmpty())
.foreach((line: String) => { // I got here "error: type mismatch; found : Unit required: String"
val pos = line.indexOf('=')
if (pos != -1) {
val key = line.substring(0, pos).trim()
val value = line.substring(pos + 1).trim()
readMeCache(siteId.get) + (key -> value)
}
})
What is the right way to fix it?

Scala underspecified types

I have the following spark code snippet .
But get the following error:
:8: error: missing parameter type.
which happens here:
val index:Int= col1(i) ; tokened +=splitted(index) + " " ; } }
^
I can't work out where it steps from as it seems like i've specified all properties. I also need to return the string so for the method to be string => string (currently it's string -> unit) This is my first time ever coding in scala so apologies if this is a stupid question
line => { var col1:Array[Int] = Array(1,2) ; var tokened:String = "" ;
var splitted:Array[String]=line.split(" ") ;
for (i<- 0 to col1.length) {
val index:Int= col1(i);
tokened +=splitted(index) + " " ;
}
}
I guess this is what you need:
(line: String) => { /* Previously missing type annotation */
var col1:Array[Int] = Array(1,2)
var tokened:String = ""
var splitted:Array[String]=line.split(" ")
for (i<- 0 to col1.length) {
val index:Int= col1(i)
tokened += splitted(index) + " "
}
tokened /* Return value */
}
In order to make the function type explicit, you could store the anonymous function in a function-typed variable:
val f: (String => String) = line => { ... }