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

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);
}

Related

condition matching in an array with case class in scala

I have a task need to find a particular string in an array:
1. if found, return its value;
2. if not found, return -1.
I wrote an "idea" code, but I don't know how to finish it correctly.
case class person(name:String, value: Int)
personList[Array[person]]
val result = personList match {
case x if x.name == "john" => x.value
case _ => -1 }
the complier reports errors at "case x if x.name"
Would this work for you?
persons.find(_.name == "john").fold(-1)(_.value)
Note: I've left the creation and/or population of the persons array up to you.
val result = personList.find(_.name=="john") match {
case some(x) => x.value
case None => -1 }

Scala - Automatic Iterator inside pattern match

I have Array Data like this : [("Bob",5),("Andy",10),("Jim",7),...(x,y)].
How to do pattern matching in Scala? so they will match automatically based on Array Data that i have provided (instead of define "Case" one by one)
i mean dont like this, pseudocode :
val x = y.match {
case "Bob" => get and print Bob's Score
case "Andy" => get and print Andy's Score
..
}
but
val x = y.match {
case automatically defined by given Array => print each'score
}
Any Idea ? thanks in advance
If printing and storing results in an array is your main concern than the following will work well:
val ls = Array(("Bob",5),("Andy",10),("Jim",7))
ls.map({case (x,y) => println(y); y}) // print and store the score in an array
A bit confused about the question however if you just wish to print all the data in the array i would go about it doing this:
val list = Array(("Foo",3),("Tom",3))
list.foreach{
case (name,score) =>
println(s"$name scored $score")
}
//output:
//Foo scored 3
//Tom scored 3
Consider
val xs = Array( ("Bob",5),("Andy",10),("Jim",7) )
for ( (name,n) <- xs ) println(s"$name scores $n")
and also
xs.foreach { t => println(s"{t._1} scores ${t._2}") }
xs.foreach { t => println(t._1 + " scores " + t._2) }
xs.foreach(println)
A simple way to print the contents of xs,
println( xs.mkString(",") )
where mkString creates a string out of xs and separates each item by a comma.
Miscellany notes
To illustrate pattern matching on Scala Array, consider
val x = xs match {
case Array( t # ("Bob", _), _*) => println("xs starts with " + t._1)
case Array() => println("xs is empty")
case _ => println("xs does not start with Bob")
}
In the first case we extract the first tuple, and neglect the rest. In the first tuple we match against string "Bob" and neglect the second item. Moreover, we bind the first tuple to tag t, which is used in the printing where we refer to its first item.
The second case means every other case not covered.

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!"))

zipWithIndex with and without case

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?

Scala pattern match on subset of random elements in a List

Can anybody suggest a efficient style to pattern match on a subset of elements in a list
containsSlice expects order and does not work with an unordered comparator list
This is what I am looking for (an inaccurate syntactical representation to drive the point)
List(1,2,3,4,5,6) match {
case x if x.contains(List(1,3)) => do something
case x if x.contains(List(2)) => else
case _ => do something else else
}
If you can live without the pattern-match,
a single "subset of elements in a list" can be identified by checking if each element in the subset is contained in the list, like such:
if( List(3,1).forall( List(1,2,3,4,5,6).contains(_) ) ) println("do something")
List(1, 2, 3, 4, 5, 6).toSet match {
case x if Set(1, 3).subsetOf(x) => println("do something")
case x if Set(2).subsetOf(x) => println("something else")
case _ => println("another thing")
}
you mean something like this? :
def [X]containsSubset(li:List[X],li2:List[X]) =
li2 match {
case Nil => true
case hd::_ => li.contains(hd) && containsSubset(li,tl)
}