Concatenate to form list scala - scala

I want to create a list of Test class.
case class Person(name:String)
case class Test (desc:String)
val list =Seq(Person("abc"),Person("def"))
val s = Option(list)
private val elems = scala.collection.mutable.ArrayBuffer[Test]()
val f =for{
l<-s
}yield {
for{
e <-l
} yield elems+=tranform(e)
}
f.toSeq
def tranform(p:Person):Test= {
Test(desc = "Hello "+p.name)
}
can anyone please help with the following
better way to avoid multiple for
I want to get List(Test("Hello abc"),Test("Hello def")) instead of using ArrayBuffer

I don't know why you're wrapping a Seq in an Option; Seq represents the no Persons case perfectly well. Is there a difference between None and Some(Seq.empty[Person]) in your application?
Assuming that you can get by without an Option[Seq[Person]]:
list.map(transform).toList

Related

Build a class instance from elements in a list

I want to build an instance of a class Something by calling the function foo on this calss for every element in a list. e.g.
val list = List(1,2,3)
should result in a call with the same effect as:
val something = somethingBuilder.foo(1).foo(2).foo(3)
Is there a way to perform this?
As I understand your question, you can do :
val list = List(1,2,3)
val something = somethingBuilder
list.foreach(something.foo)
I am assuming that you care for the returned value of your builder call. Then following code will print Builder(6):
val list = List(1,2,3)
case class Builder(val i: Int){
def build(j: Int) = Builder(i+j)
}
val finalBuilder = list.foldLeft(Builder(0))(_.build(_))
println(finalBuilder)
If you only care for the side effect, maybe Rafael's solution is more adequate (although using the foldLeft will of course also trigger the side-effect).
This can be one of the solution.
val lst = List(1,2,3,4,5)
class Builder(val i: Int){
def Foo() {
println("Value is initialized: " + i)
}
}
lst.map( a => new Builder(a).Foo())
But the disclaimer, it does generates the list of empty lists as a side effect
print(lst.map( a => new Builder(a).Foo()))

Combine Scala Future[Seq[X]] with Seq[Future[Y]] to produce Future[(X,Seq[Y])]

I have below relationship in my entity classes,
customer -> * Invoice
now I have to implement a method which returns customers with their invoices
type CustomerWithInvoices = (Custimer,Seq[Invoice])
def findCustomerWitnInvoices:Future[Seq[CustomerWithInvoices]] = {
for{
customers <- findCustomers
eventualInvoices: Seq[Future[Seq[Invoice]]] = customers.map(customer => findInvoicesByCustomer(customer))
} yield ???
}
using existing repository methods as below
def findCustomers:Future[Seq[Customers]] = {...}
def findInvoicesByCustomer(customer:Customer):Future[Seq[Invoice]] = {...}
I try to use for expression as above but I can't figure the proper way to do it, as I'm fairly new to Scala, highly appreciate any help..
i would use Future.sequence, the simplified method signature is
sequence takes M[Future[A]] and returns Future[M[A]]
That is what we need to solve your problem, here's the code i would write:
val eventualCustomersWithInvoices: Future[Seq[(Customer, Seq[Invoice])]] = for {
customers <- findCustomers()
eventualInvoices <- Future.sequence(customers.map(customer => findInvoicesByCustomer(customer)))
} yield eventualInvoices
note that the type of eventualInvoices is Future[Seq[(Customer, Seq[Invoice])]] hence Future[Seq[CustomerWithInvoices]]

Use ScalaCheck generator inside another generator

I have a generator that creates a very compelx object. I cannot create this object through something like
val myGen = for{
a <- Gen.choose(-10,10)
...
} yield new MyClass(a,b,c,...)
I tried an approach of creating a custom generator like this
val myComplexGen :Gen[ComplexObject] = {
...
val myTempVariable = Gen.choose(-10,10)
val otherTempVal = Gen.choose(100,2000)
new MyComplexObject(myTempVariable,otherTempVal,...)
}
and then
test("myTest") {
forAll(myComplexGen){ complexObj =>
... // Here, complexObj.myTempVariable is always the same through all the iterations
}
}
While this works, the values generated are always the same. The inner Gen.choose yield always the same value.
Is there any way I can write a custom Gen with its own logic, and use inner Gen.choose inside, that would be random ?
I've been able to workaround the problem. The solution is definitely not elegant but that's the only way I could work it out.
I have transformed myComplexGen into a def, and called it inside another gen with dummy variables
def myComplexGen :ComplexObject = {
...
val myTempVariable = Gen.choose(-10,10)
val otherTempVal = Gen.choose(100,2000)
new MyComplexObject(myTempVariable,otherTempVal,...)
}
val realComplexGen :Gen[ComplexObject] = for {
i <- Gen.choose(0,10) // Not actually used, but for cannot be empty
} yield myComplexGen()
Now I can use realComplexGenin a forAll and the object is really random.

How to create a play.api.libs.iteratee.Enumerator which inserts some data between the items of a given Enumerator?

I use Play framework with ReactiveMongo. Most of ReactiveMongo APIs are based on the Play Enumerator. As long as I fetch some data from MongoDB and return it "as-is" asynchronously, everything is fine. Also the transformation of the data, like converting BSON to String, using Enumerator.map is obvious.
But today I faced a problem which at the bottom line narrowed to the following code. I wasted half of the day trying to create an Enumerator which would consume items from the given Enumerator and insert some items between them. It is important not to load all the items at once, as there could be many of them (the code example has only two items "1" and "2"). But semantically it is similar to mkString of the collections. I am sure it can be done very easily, but the best I could come with - was this code. Very similar code creating an Enumerator using Concurrent.broadcast serves me well for WebSockets. But here even that does not work. The HTTP response never comes back. When I look at Enumeratee, it looks that it is supposed to provide such functionality, but I could not find the way to do the trick.
P.S. Tried to call chan.eofAndEnd in Iteratee.mapDone, and chunked(enums >>> Enumerator.eof instead of chunked(enums) - did not help. Sometimes the response comes back, but does not contain the correct data. What do I miss?
def trans(in:Enumerator[String]):Enumerator[String] = {
val (res, chan) = Concurrent.broadcast[String]
val iter = Iteratee.fold(true) { (isFirst, curr:String) =>
if (!isFirst)
chan.push("<-------->")
chan.push(curr)
false
}
in.apply(iter)
res
}
def enums:Enumerator[String] = {
val en12 = Enumerator[String]("1", "2")
trans(en12)
//en12 //if I comment the previous line and uncomment this, it prints "12" as expected
}
def enum = Action {
Ok.chunked(enums)
}
Here is my solution which I believe to be correct for this type of problem. Comments are welcome:
def fill[From](
prefix: From => Enumerator[From],
infix: (From, From) => Enumerator[From],
suffix: From => Enumerator[From]
)(implicit ec:ExecutionContext) = new Enumeratee[From, From] {
override def applyOn[A](inner: Iteratee[From, A]): Iteratee[From, Iteratee[From, A]] = {
//type of the state we will use for fold
case class State(prev:Option[From], it:Iteratee[From, A])
Iteratee.foldM(State(None, inner)) { (prevState, newItem:From) =>
val toInsert = prevState.prev match {
case None => prefix(newItem)
case Some(prevItem) => infix (prevItem, newItem)
}
for(newIt <- toInsert >>> Enumerator(newItem) |>> prevState.it)
yield State(Some(newItem), newIt)
} mapM {
case State(None, it) => //this is possible when our input was empty
Future.successful(it)
case State(Some(lastItem), it) =>
suffix(lastItem) |>> it
}
}
}
// if there are missing integers between from and to, fill that gap with 0
def fillGap(from:Int, to:Int)(implicit ec:ExecutionContext) = Enumerator enumerate List.fill(to-from-1)(0)
def fillFrom(x:Int)(input:Int)(implicit ec:ExecutionContext) = fillGap(x, input)
def fillTo(x:Int)(input:Int)(implicit ec:ExecutionContext) = fillGap(input, x)
val ints = Enumerator(10, 12, 15)
val toStr = Enumeratee.map[Int] (_.toString)
val infill = fill(
fillFrom(5),
fillGap,
fillTo(20)
)
val res = ints &> infill &> toStr // res will have 0,0,0,0,10,0,12,0,0,15,0,0,0,0
You wrote that you are working with WebSockets, so why don't you use dedicated solution for that? What you wrote is better for Server-Sent-Events rather than WS. As I understood you, you want to filter your results before sending them back to client? If its correct then you Enumeratee instead of Enumerator. Enumeratee is transformation from-to. This is very good piece of code how to use Enumeratee. May be is not directly about what you need but I found there inspiration for my project. Maybe when you analyze given code you would find best solution.

Filling a Scala immutable Map from a database table

I have a SQL database table with the following structure:
create table category_value (
category varchar(25),
property varchar(25)
);
I want to read this into a Scala Map[String, Set[String]] where each entry in the map is a set of all of the property values that are in the same category.
I would like to do it in a "functional" style with no mutable data (other than the database result set).
Following on the Clojure loop construct, here is what I have come up with:
def fillMap(statement: java.sql.Statement): Map[String, Set[String]] = {
val resultSet = statement.executeQuery("select category, property from category_value")
#tailrec
def loop(m: Map[String, Set[String]]): Map[String, Set[String]] = {
if (resultSet.next) {
val category = resultSet.getString("category")
val property = resultSet.getString("property")
loop(m + (category -> m.getOrElse(category, Set.empty)))
} else m
}
loop(Map.empty)
}
Is there a better way to do this, without using mutable data structures?
If you like, you could try something around
def fillMap(statement: java.sql.Statement): Map[String, Set[String]] = {
val resultSet = statement.executeQuery("select category, property from category_value")
Iterator.continually((resultSet, resultSet.next)).takeWhile(_._2).map(_._1).map{ res =>
val category = res.getString("category")
val property = res.getString("property")
(category, property)
}.toIterable.groupBy(_._1).mapValues(_.map(_._2).toSet)
}
Untested, because I don’t have a proper sql.Statement. And the groupBy part might need some more love to look nice.
Edit: Added the requested changes.
There are two parts to this problem.
Getting the data out of the database and into a list of rows.
I would use a Spring SimpleJdbcOperations for the database access, so that things at least appear functional, even though the ResultSet is being changed behind the scenes.
First, some a simple conversion to let us use a closure to map each row:
implicit def rowMapper[T<:AnyRef](func: (ResultSet)=>T) =
new ParameterizedRowMapper[T]{
override def mapRow(rs:ResultSet, row:Int):T = func(rs)
}
Then let's define a data structure to store the results. (You could use a tuple, but defining my own case class has advantage of being just a little bit clearer regarding the names of things.)
case class CategoryValue(category:String, property:String)
Now select from the database
val db:SimpleJdbcOperations = //get this somehow
val resultList:java.util.List[CategoryValue] =
db.query("select category, property from category_value",
{ rs:ResultSet => CategoryValue(rs.getString(1),rs.getString(2)) } )
Converting the data from a list of rows into the format that you actually want
import scala.collection.JavaConversions._
val result:Map[String,Set[String]] =
resultList.groupBy(_.category).mapValues(_.map(_.property).toSet)
(You can omit the type annotations. I've included them to make it clear what's going on.)
Builders are built for this purpose. Get one via the desired collection type companion, e.g. HashMap.newBuilder[String, Set[String]].
This solution is basically the same as my other solution, but it doesn't use Spring, and the logic for converting a ResultSet to some sort of list is simpler than Debilski's solution.
def streamFromResultSet[T](rs:ResultSet)(func: ResultSet => T):Stream[T] = {
if (rs.next())
func(rs) #:: streamFromResultSet(rs)(func)
else
rs.close()
Stream.empty
}
def fillMap(statement:java.sql.Statement):Map[String,Set[String]] = {
case class CategoryValue(category:String, property:String)
val resultSet = statement.executeQuery("""
select category, property from category_value
""")
val queryResult = streamFromResultSet(resultSet){rs =>
CategoryValue(rs.getString(1),rs.getString(2))
}
queryResult.groupBy(_.category).mapValues(_.map(_.property).toSet)
}
There is only one approach I can think of that does not include either mutable state or extensive copying*. It is actually a very basic technique I learnt in my first term studying CS. Here goes, abstracting from the database stuff:
def empty[K,V](k : K) : Option[V] = None
def add[K,V](m : K => Option[V])(k : K, v : V) : K => Option[V] = q => {
if ( k == q ) {
Some(v)
}
else {
m(q)
}
}
def build[K,V](input : TraversableOnce[(K,V)]) : K => Option[V] = {
input.foldLeft(empty[K,V]_)((m,i) => add(m)(i._1, i._2))
}
Usage example:
val map = build(List(("a",1),("b",2)))
println("a " + map("a"))
println("b " + map("b"))
println("c " + map("c"))
> a Some(1)
> b Some(2)
> c None
Of course, the resulting function does not have type Map (nor any of its benefits) and has linear lookup costs. I guess you could implement something in a similar way that mimicks simple search trees.
(*) I am talking concepts here. In reality, things like value sharing might enable e.g. mutable list constructions without memory overhead.