zipWithIndex with and without case - scala

How are the following 2 pieces of code equivalent? (how does case work)
list.zipWithIndex.flatMap{
rowAndIndex =>
rowAndIndex._1.zipWithIndex
}
and
list.zipWithIndex.flatMap {
case (rowAndIndex, r) =>
rowAndIndex.zipWithIndex
}

You are probably confused by wrong names in second sample. I changed it to:
list.zipWithIndex.flatMap {
case (row, index) =>
row.zipWithIndex
}
This is short version of:
list.zipWithIndex.flatMap { rowAndIndex =>
rowAndIndex match {
case (row, index) => row.zipWithIndex
}
}

I preferred the first one, since every element here is case (rowAndIndex, r), check it every time seems unnecessary.
And, it seems that you actually don't want the first 'index', why not just use:
list.map(s => s.zipWithIndex).flatten
By the way, I just put following code to http://scalass.com/tryout
val list = List("Abby", "Jim", "Tony")
val a = list.zipWithIndex.flatMap({a =>
a._1.zipWithIndex})
println(a)
val b = list.zipWithIndex.flatMap({case (rowAndIndex, r) =>
rowAndIndex.zipWithIndex})
println(b)
val d = list.map(s => s.zipWithIndex).flatten
println(d)
The output is all like
List((A,0), (b,1), (b,2), (y,3), (J,0), (i,1), (m,2), (T,0), (o,1), (n,2), (y,3))
This is what you want, right?

Related

Scala return variable type after future is complete Add Comment Collapse

I've got a problem with returning a list after handling futures in scala. My code looks like this:
def getElements(arrayOfIds: Future[Seq[Int]]): Future[Seq[Element]] = {
var elementArray: Seq[Element] = Seq()
arrayOfIds.map {
ids => ids.map(id => dto.getElementById(id).map {
case Some(element) => elementArray = elementArray :+ element
case None => println("Element not found")
})
}
arrayOfIds.onComplete(_ => elementArray)
}
I'd like to do something like .onComplete, however the return type is
Unit and I'd like to return a Future[Seq[Whatever]]. Is there clean way to handle futures like this? Thanks!
Please provide the type of function dto.getElementById. If it is Int => Future[Option[Element]], then:
def getElements(arrayOfIds: Future[Seq[Int]]): Future[Seq[Element]] = {
val allElements: Future[Seq[Option[Element]]] = arrayOfIds.flatMap( ids =>
Future.sequence(ids.map(dto.getElementById))
)
allElements.map(_.flatMap{
case None => println();None
case some => some
})
}
Without logging, it would be:
arrayOfIds.flatMap( ids => Future.traverse(ids.map(dto.getElementById))(_.flatten))
Instead of assigning the result to a mutable variable, return it from the continuation of the Future. You can use flatMap to extract only the Element results which actually contain a value:
def getElements(arrayOfIds: Future[Seq[Int]]): Future[Seq[Element]] = {
arrayOfIds.flatMap(id => Future.fold(id.map(getElementById))(Seq.empty[Element])(_ ++ _))
}

Scala zipWithIndex over a sequence of Strings, do something different with last entry

I have a Seq[String] the represent a file, every String is a line in the file.
I'm iterating over the lines and parsing the record:
fileLines.zipWithIndex.foreach {
case(fileLine, filePosition) => parseRecord(fileLine, filePosition)
}
Now, for the last record I need to do a different parsing. Let's say parseLastRecord(). What is the best Scala-way to do it?
The main reason for my question is that it would be totally fine to do the last line parsing inside parseRecord that I already use, but, I don't want to pass the filePosition+totalSize into it...
While pattern matching you can check the index and call whichever function you want to call from there.
eg. if last element I'm printing something otherwise each element in following example.
List(1, 2, 3, 4).zipWithIndex.foreach{
case (element, index) if index == 3 => println("last element")
case (element, index) => println(element)
}
output
1
2
3
last element
So, your case would be something as below,
fileLines.zipWithIndex.foreach {
case(fileLine, filePosition) if filePosition == fileLines.length-1 => parseLastRecord(fileLine, filePosition)
case(fileLine, filePosition) => parseRecord(fileLine, filePosition)
}
using pattern matching
val l = List(1,2,3,4)
val spe = l.length - 1
l.zipWithIndex.foreach{ case(item, pos) => {pos match { case `spe` => println(s"$item $pos special"); case _ => println(s"$item $pos");}}}
in your case
val last = fileLines.length - 1
fileLines.zipWithIndex.foreach {
case(fileLine, filePosition) => {filePosition match {
case `last` => parseLastRecord(fileLine, filePosition)
case _ => parseRecord(fileLine, filePosition);
}

Scala - dynamically choose function

I'm trying to dynamically choose a function, as follows:
val yld: (Nothing => Object) = {
column.getType match {
case PrimitiveType.PrimitiveTypeName.BINARY => new String(creader.getBinary.getBytes)
case PrimitiveType.PrimitiveTypeName.BOOLEAN => creader.getBoolean
case PrimitiveType.PrimitiveTypeName.DOUBLE => creader.getDouble
case PrimitiveType.PrimitiveTypeName.FLOAT => creader.getFloat
case PrimitiveType.PrimitiveTypeName.INT32 => creader.getInteger
case PrimitiveType.PrimitiveTypeName.INT64 => creader.getLong
case PrimitiveType.PrimitiveTypeName.INT96 => new String(creader.getBinary.getBytes)
case PrimitiveType.PrimitiveTypeName.FIXED_LEN_BYTE_ARRAY => new String(creader.getBinary.getBytes)
}
}
Question: However, the inner functions (e.g. creader.getBoolean, etc.) are (obviously) executed at the time of the match. How do I capture those functions as objects to execute at a later time rather than having them execute when yld is assigned?
Context:
This is so that in a later for loop, I don't have to match again:
for (i <- 0L to 900000) {
println(yld)
}
Because my object creader is an iterator on column-stored data, being able to make the type decision only one time should be more efficient than having to make it every time, i.e.
for (i <- 0L to 900000) {
column.getType match {
case PrimitiveType.PrimitiveTypeName.BINARY => println(new String(creader.getBinary.getBytes))
case PrimitiveType.PrimitiveTypeName.BOOLEAN => println(creader.getBoolean)
case PrimitiveType.PrimitiveTypeName.DOUBLE => println(creader.getDouble)
case PrimitiveType.PrimitiveTypeName.FLOAT => println(creader.getFloat)
case PrimitiveType.PrimitiveTypeName.INT32 => println(creader.getInteger)
case PrimitiveType.PrimitiveTypeName.INT64 => println(creader.getLong)
case PrimitiveType.PrimitiveTypeName.INT96 => println(new String(creader.getBinary.getBytes))
case PrimitiveType.PrimitiveTypeName.FIXED_LEN_BYTE_ARRAY => println(new String(creader.getBinary.getBytes))
}
}
If you have a method def foo = 42 you can convert it to a function and assign it to a val by val func = foo _.

Scala filter return only one (or specific number) of results

What is the best Scala idiomatic approach to verify that filter returns only one results (or specific amount in that matter), and if the amount correct, to continue with it?
For example:
val myFilteredListWithDesiredOneItem = unfilteredList
.filter(x => x.getId.equals(something))
.VERIFY AMOUNT
.toList
Consider this for a list of type T,
val myFilteredListWithDesiredOneItem = {
val xs = unfilteredList.filter(x => x.getId.equals(something))
if (xs.size == n) xs.toList
else List.empty[T]
}
Not a oneliner, the code remains simple none the less.
Try a match with guards, perhaps?
list.filter(...) match {
case Nil => // empty
case a if (a.size == 5) => // five items
case b#(List(item1, item2) => // two (explicit) items
case _ => // default
}
Something like this perhaps:
Option(list.filter(filterFunc))
.filter(_.size == n)
.getOrElse(throw new Exception("wrong size!"))

Processing Set of Sets and return a flat Iterable

val input=Set(Set("a","b"),Set("b","c"))
I want this:
Map("a"->1,"b"->2,"c"->1)
What is the best functional approach for implementing such functionality?
Using yield keyword results in nested Iterables:
output = for(firstlevel<-input) yield for(item<-firstlevel) yield item
update: incorporated the suggestion to use input.toSeq.flatten
instead of input.toSeq flatMap { _.toSeq }
convert to a single sequence of values...
input.toSeq.flatten
...group values that match...
input.toSeq.flatten groupBy { identity }
...and count
input.toSeq.flatten groupBy { identity } mapValues { _.size }
If you want to use for-comprehension and yield:
output = for{
(set,idx) <- input.zipWithIndex
item <- set
} yield (item -> idx)
The code in your last line can be simplified (but does not what you want):
output = for{
set <- input
item <- set
} yield item
Oh boy, that's so ugly...
input.foldLeft(Map[String,Int]())((m,s) =>
s.foldLeft(m)((n,t) => n + (t -> (1 + n.getOrElse(t,0)))))
[Edit]
The Collection-API needs really a method for "merging" two Maps (or did I just overlook it???), e.g.
def merge[A,B](m1: Map[A,B], m2:Map[A,B])(f: (B,B)=>B):Map[A,B] =
m1.foldLeft(m2)((m,t) =>
m + (t._1 -> m.get(t._1).map(k => f(k,t._2)).getOrElse(t._2)))
With this you could write something like:
input.map(_.map(x => x -> 1).toMap).reduceLeft(merge(_,_)(_+_))
[Edit2]
With Kevin's idea merge could be written as
def merge[A,B](m1: Map[A,B], m2:Map[A,B])(f: (B,B)=>B):Map[A,B] =
m1.keys ++ m2.keys map {k => k ->
List(m1.get(k), m2.get(k)).flatten.reduceLeft(f)} toMap
Seems like my Scala-Fu is still too weak. What's the best way to express
(o1,o2) match {
case (Some(x),Some(y)) => Some(f(x,y))
case (Some(x), _) => Some(x)
case (_, Some(y)) => Some(y)
case => error("crack in the time-space-continuum")
}
?