Scala, Casbah - How to convert List to MongoDBList? - scala

Is there an easy way to turn List into MongoDBList(or BasicDBList) ?

scala> val list = List("foo", "bar")
list: List[java.lang.String] = List(foo, bar)
scala> val dbList = MongoDBList(list:_*)
dbList: com.mongodb.casbah.commons.MongoDBList = [ "foo" , "bar"]
Hint: always read source code at first. It can provide many answers to your questions and will be useful BTW. It may be hard at first time, but then it became more and more natural.

Related

Indexing/Slicing of Collections in Scala

I saw some really cool methods to operate on Scala Collections but I wanted to know how can one do the slicing operation in Scala? I see methods like dropLeft take but curious to know if something simpler like indexing or slice exists in Scala.
For example:
val aString = "I want this word"
val aList = List(1,2,3,4)
should return:
val slicedString = aString.slice(7,11) => "this" //JavaScript type
and
val slicedList = aList.slice(0,2) => List(1,2) //JavaScript type
or indexing like how it's done in python:
val slicedString = aString(7:11) => "this"
val slicedList = aList(0:2) => List(1,2)
Had you bothered to consult the ScalaDocs you would have found what you're looking for.
aString.slice(7,11) //res0: String = this
aList.slice(0,2) //res1: List[Int] = List(1, 2)

How would I alter a list within a list in Scala using functional programming

Imagine I have a list[list[object]]
and I wanted to get a list[list[object.field]]
How would i be able to do this through functional programming
as in
if val list = list[list[object]]
i tried
val newList = list(_)(_1.map(object.field))
but this gave me an error and I am confused
I just started functional programming and scala so there might be something completely illogical with this statement
You need to use map as following
case class Obj(field: String)
val list = List[List[Obj]]()
val fields: List[List[String]] = list.map(_.map(_.field))
or same as
val fields: List[List[String]] = list.map(innerList => innerList.map(obj => obj.field))
or if you want to have a flattened list of fields
val fields: List[String] = list.flatMap(_.map(_.field))

scala: list as input and output of function

I am new to scala. I have a very simple problem.
Given a list in python
x=[1, 100, "a1", "b1"]
I can write a function that will return the last two elements
def f(w):
if w[0]>=1 and w[1]<=100:
return ([w[2],w[3]])
How do I do the equivalent in scala
val v= List(1, 100, "a1", "b1")
def g(L:List[Any]): List[String] = {
if( L(0)>=1 & L(1)<=100 ) {return List(L(2), L(3))}
}
val w=g(v)
This gets me the error
List[Any] = List(1, 100, a, b)
Incomplete expression
You can't get a List[String] from a List[Any]. (Well, you can, but it's a really bad thing to do.)
Don't, don't, don't create a List[Any]. Unlike Python, Scala is a strictly typed language, which means that the compiler keeps a close watch on the type of each variable and every collection. When the compiler looses track of the List type it becomes List[Any] and you've lost all the assistance the compiler offers to help write programs that don't crash.
To mix types in a collection you can use tuples. Here's the type-safe Scala way to write your g() method.
def g(tup: (Int,Int,String,String)): List[String] =
if (tup._1 >= 1 & tup._2 <= 100) List(tup._3, tup._4)
else List()
Usage:
val v = (1, 100, "a1", "b1")
val w = g(v) //w: List[String] = List(a1, b1)
It seems like you have a typo here:
if(L(0)>=1 & L(1<=100)) {return List(L(2), L(3))}
Wouldn't it be like this?
if(L(0)>=1 & L(1)<=100) {return List(L(2), L(3))}
The error seems to point out there's something wrong with that extra bracket there.
scala> List(1,2,3,4,5).takeRight(2)
res44: List[Int] = List(4, 5)
You can use a built in function in Scala that does this!

Scala collections: Is there a safe map operation?

Let's say that I have a List (or the values in a Map), and i want to perform an operation on each item. But unfortunately, for whatever reason, this list of values can contain nulls.
scala> val players = List("Messi", null, "Xavi", "Iniesta", null)
players: List[java.lang.String] = List(Messi, null, Xavi, Iniesta, null)
In order to avoid blowing up with a NPE, i need to do the following:
scala> players.filterNot(_ == null ).map(_.toUpperCase)
res84: List[java.lang.String] = List(MESSI, XAVI, INIESTA)
Is there any better way of doing this?
Ideally something like:
players.safeMap(_.toUpperCase)
On the scala-language mailing list, Simon proposed this:
players.filter ( null !=).map(_.toUpperCase )
which is shorter version of my original take, and as short as you can get without a dedicated method.
Even better, Stefan and Kevin proposed the method withFilter which will return a lazy proxy, so both operations can be merged.
players.withFilter ( null !=).map(_.toUpperCase )
If you can’t avoid nulls (e.g. if you get your list from Java code), another alternative is to use collect instead of map:
scala> players.collect { case player if player != null => player.toUpperCase }
res0: List[java.lang.String] = List(MESSI, XAVI, INIESTA)
I'd do this:
players flatMap Option map (_.toUpperCase)
But that's worse than collect. filter + map is always better done with collect.
You could convert to a list of Option[String]:
scala> val optionPlayers = players.map(Option(_))
optionPlayers: List[Option[java.lang.String]] = List(Some(Messi), None, Some(Xavi), Some(Iniesta), None)
Option is universally preferred to null and it gives you a lot of flexibility in how you can safely handle the data. Here's are thee easy ways to get the result you were looking for:
scala> optionPlayers.collect { case Some(s) => s.toUpperCase }
res0: List[java.lang.String] = List(MESSI, XAVI, INIESTA)
scala> optionPlayers.flatMap(_.map(_.toUpperCase))
res1: List[java.lang.String] = List(MESSI, XAVI, INIESTA)
scala> optionPlayers.flatten.map(_.toUpperCase)
res2: List[java.lang.String] = List(MESSI, XAVI, INIESTA)
You can find a lot more information about Option in other StackOverflow questions or by searching the web.
Or, you can always just define that safeMap method you wanted as an implicit on List:
implicit def enhanceList[T](list: List[T]) = new {
def safeMap[R](f: T => R) = list.filterNot(_ == null).map(f)
}
so you can do:
scala> players.safeMap(_.toUpperCase)
res4: List[java.lang.String] = List(MESSI, XAVI, INIESTA)
Though if you define an implicit, you might want to use a CanBuildFrom style like the basic collections do to make it work on more than just List. You can find more information about that elsewhere.

Simple Scala coding question

Suppose I have list countries of type List[String] and map capitals of type Map[String, String]. Now I would like to write a functionpairs(countries:List[String], capitals:Map[String, String]):Seq[(String, String)]to return a sequence of pairs (country, capital) and print an error if the capital for some country is not found. What is the best way to do that?
To start with, your Map[String,String] is already a Seq[(String,String)], you can formalise this a bit by calling toSeq if you wish:
val xs = Map("UK" -> "London", "France" -> "Paris")
xs.toSeq
// yields a Seq[(String, String)]
So the problem then boils down to finding countries that aren't in the map. You have two ways of getting a collection of those countries that are represented.
The keys method will return an Iterator[String], whilst keySet will return a Set[String]. Let's favour the latter:
val countriesWithCapitals = xs.keySet
val allCountries = List("France", "UK", "Italy")
val countriesWithoutCapitals = allCountries.toSet -- countriesWithCapitals
//yields Set("Italy")
Convert that into an error in whatever way you see fit.
countries.map(x=>(x, capitals(x)))