replace string variable in Scala for solution - scala

I have a variable which has the following data structure, I want to replace all "foo" with all "goo" for the String part. Is there any one line neat code to do that? Want to see if any smart solutions to skip to write a loop. :)
var result = List[List[(List[String], Double)]]
regards,
Lin

I am not sure if I got it right but maybe this is what you are looking for?
scala> val a: List[List[(List[String], Double)]] = List(List((List("foo asd", "asd foo"), 2.6)))
scala> a map (_ map { case (k, v) => (k map (_.replaceAll("foo", "goo")), v) })
res1: List[List[(List[String], Double)]] = List(List((List(goo asd, asd goo),2.6)))
Edit
to answer the comment let me first remove spaces and use dots
scala> a.map(_.map { case (k, v) => (k.map(_.replaceAll("foo", "goo")), v) })
and now, expand _.method(param) to x => x.method(param)
scala> a.map(b => b.map { case (k, v) => (k.map(c => c.replaceAll("foo", "goo")), v) })
You have 3 levels of nested lists, and one is inside a tuple, it won't be pretty, you need to map over each of them and extract last one from tuple.

scala> val l = List(List((List("foo","afoo"),3.4),(List("gfoo","cfoo"),5.6)))
l: List[List[(List[String], Double)]] = List(List((List(foo, afoo),3.4), (List(gfoo, cfoo),5.6)))
scala> def replaceFoo(y:List[String]) = y.map(s => s.replace("foo","goo"))
replaceFoo: (y: List[String])List[String]
scala> l.map(x => x.map(y => (replaceFoo(y._1),y._2)))
res0: List[List[(List[String], Double)]] = List(List((List(goo, agoo),3.4), (List(ggoo, cgoo),5.6)))

Related

Convert a Seq["key1=val1"] to a Map[String, String] in Scala

I have the following Seq[String], with all strings with = delimiter.
keysVals = ["Country=France", "City=Paris"]
I would like to convert it into a Map[String, String], such as
result = Map("Country"->"France", "City"->"Paris")
How to do that, please?
The shortest way seems to be
data.map { case s"${k}=${v}" => k -> v }.toMap
using StringContext.s.unapplySeq as in
val data = List("Country=France", "City=Paris")
println(data.map { case s"${k}=${v}" => k -> v }.toMap)
(thanks #Luis Miguel Mejía Suárez).
Alternatively, with Regex pattern-matching:
val KeyValuePattern = "([^=]+)=([^=]+)".r
data.map { case KeyValuePattern(k, v) => k -> v }.toMap
With good old String.split:
data.map(str => str.split("=") match { case Array(k, v) => k -> v }).toMap

Reduce by key in an array of arrays in Scala

I've created an array in Scala
val L = Array((1,Array(one, two, one)), (2,Array(one, three, three)))
And I want to get this result:
Array((1,(one,2), (two,1)), (2,(one,1),(three,2)))
I did
val LL = L.map({case (s, contents) => (s, contents.map(s=>(s,1)))})
and got
LL = Array((1,Array((one,1), (two,1), (one,1))), (2,Array((one,1), (three,1), (three,1))))
and I want to do a reduceByKey to have that result but it doesn't seem to work. Any help?
Try:
L.map { case (key, values) =>
(key, values.groupBy(identity).mapValues(_.size).toArray)
}
Use foldLeft to iterate on each second value of the array item and count the occurrence of strings in each Array.
Scala repl
scala> val arr: Array[(Int, Array[String])] = Array((1, Array("one", "one", "two")))
arr: Array[(Int, Array[String])] = Array((1,Array(one, one, two)))
scala> arr.map { case (k, v) => k -> (v.foldLeft(Map.empty[String, Int])((r, c) => r.get(c).map(x => r.updated(c, x + 1)).getOrElse(r.updated(c, 1))).toArray) }
res16: Array[(Int, Array[(String, Int)])] = Array((1,Array((one,2), (two,1))))

Scala - Join List of tuples by Key

I am looking for a way to join two list of tuples in scala to get same result than Apache spark gives me using join function.
Example:
Having two list of tuples such us:
val l1 = List((1,1),(1,2),(2,1),(2,2))
l1: List[(Int, Int)] = List((1,1), (1,2), (2,1), (2,2))
val l2 = List((1,(1,2)), (2,(2,3)))
l2: List[(Int, (Int, Int))] = List((1,(1,2)), (2,(2,3)))
What is the best way to join by key both list to get the following result?
l3: List[(Int,(Int,(Int,Int)))] = ((1,(1,(1,2))),(1,(2,(1,2))),(2,(1,(2,3))),(2,(2,(2,3))))
You can use a for comprehension and take advantage of using the '`' in the pattern matching. That is, it will match only when keys from the first list are the same with the ones in the second list ("`k`" means the key in the tuple must be equal to the value of k).
val res = for {
(k, v1) <- l1
(`k`, v2) <- l2
} yield (k, (v1, v2))
I hope you find this helpful.
You might want do do something like this:
val l3=l1.map(tup1 => l2.filter(tup2 => tup1._1==tup2._1).map(tup2 => (tup1._1, (tup1._2, tup2._2)))).flatten
It Matches the same Indexes, creates sublists and then combines the list of lists with the flatten-command
This results to:
List((1,(1,(1,2))), (1,(2,(1,2))), (2,(1,(2,3))), (2,(2,(2,3))))
Try something like this:
val l2Map = l2.toMap
val l3 = l1.flatMap { case (k, v1) => l2Map.get(k).map(v2 => (k, (v1, v2))) }
what can be rewritten to more general form using implicits:
package some.package
import scala.collection.TraversableLike
import scala.collection.generic.CanBuildFrom
package object collection {
implicit class PairTraversable[K, V, C[A] <: TraversableLike[A, C[A]]](val seq: C[(K, V)]) {
def join[V2, C2[A] <: TraversableLike[A, C2[A]]](other: C2[(K, V2)])
(implicit canBuildFrom: CanBuildFrom[C[(K, V)], (K, (V, V2)), C[(K, (V, V2))]]): C[(K, (V, V2))] = {
val otherMap = other.toMap
seq.flatMap { case (k, v1) => otherMap.get(k).map(v2 => (k, (v1, v2))) }
}
}
}
and then simply:
import some.package.collection.PairTraversable
val l3 = l1.join(l2)
This solution converts second sequence to map (so it consumes some additional memory), but is much faster, than solutions in other answers (compare it for large collections, e.g. 10000 elements, on my laptop it is 5ms vs 2500ms).
Little late. This solution will give you back the original size of l1 and return Option(None) for missing values in l2. (Left join instead of inner join)
val m2 = l2.map{ case(k,v) => (k -> v)}.toMap
val res2 = l1.map { case(k,v) =>
val v2 = m2.get(k)
(k, (v, v2))
}

Scala - state while looping through a list

Newbie question.
I am looping through a list and need keep state in between the items.
For instance
val l = List("a", "1", "2", "3", "b", "4")
var state: String = ""
l.foreach(o => {
if (toInt(o).isEmpty) state = o else println(state + o.toString)
})
what's the alternative for the usage of var here?
You should keep in mind that it's sometimes (read: when it makes the code more readable and maintainable by others) okay to use mutability when performing some operation that's easily expressed with mutable state as long as that mutable state is confined to as little of your program as possible. Using (e.g.) foldLeft to maintain an accumulator here without using a var doesn't gain you much.
That said, here's one way to go about doing this:
val listOfThings: Seq[Either[Char, Int]] = Seq(Left('a'), Right(11), Right(212), Left('b'), Right(89))
val result = listOfThings.foldLeft(Seq[(Char, Seq[Int])]()) {
case (accumulator, Left(nextChar)) => accumulator :+ (nextChar, Seq.empty)
case (accumulator, Right(nextInt)) =>
val (currentChar, currentSequence) = accumulator.last
accumulator.dropRight(1) :+ (currentChar, currentSequence :+ nextInt)
}
result foreach {
case (char, numbers) => println(numbers.map(num => s"$char-$num").mkString(" "))
}
Use foldLeft:
l.foldLeft(""){ (state, o) =>
if(toInt(o).isEmpty) o
else {
println(state + o.toString)
state
}
}
Pass an arg:
scala> def collapse(header: String, vs: List[String]): Unit = vs match {
| case Nil =>
| case h :: t if h.forall(Character.isDigit) => println(s"$header$h") ; collapse(header, t)
| case h :: t => collapse(h, t)
| }
collapse: (header: String, vs: List[String])Unit
scala> collapse("", vs)
a1
a2
a3
b4
As simple as:
val list: List[Int] = List.range(1, 10) // Create list
def updateState(i : Int) : Int = i + 1 // Generate new state, just add one to each position. That will be the state
list.foldRight[List[(Int,Int)]](List())((a, b) => (a, updateState(a)) :: b)
Note that the result is a list of Tuple2: (Element, State), and each state depends on the element of the list.
Hope this helps
There are two major options to pass a state in functional programming when processing collections (I assume you want to get your result as a variable):
Recursion (classic)
val xs = List("a", "11", "212", "b", "89")
#annotation.tailrec
def fold(seq: ListBuffer[(String, ListBuffer[String])],
xs: Seq[String]): ListBuffer[(String, ListBuffer[String])] = {
(seq, xs) match {
case (_, Nil) =>
seq
case (_, c :: tail) if toInt(c).isEmpty =>
fold(seq :+ ((c, ListBuffer[String]())), tail)
case (init :+ ((c, seq)), i :: tail) =>
fold(init :+ ((c, seq :+ i)), tail)
}
}
val result =
fold(ListBuffer[(String, ListBuffer[String])](), xs)
// Get rid of mutable ListBuffer
.toSeq
.map {
case (c, seq) =>
(c, seq.toSeq)
}
//> List((a,List(11, 212)), (b,List(89)))
foldLeft et al.
val xs = List("a", "11", "212", "b", "89")
val result =
xs.foldLeft(
ListBuffer[(String, ListBuffer[String])]()
) {
case (seq, c) if toInt(c).isEmpty =>
seq :+ ((c, ListBuffer[String]()))
case (init :+ ((c, seq)), i) =>
init :+ ((c, seq :+ i))
}
// Get rid of mutable ListBuffer
.toSeq
.map {
case (c, seq) =>
(c, seq.toSeq)
}
//> List((a,List(11, 212)), (b,List(89)))
Which one is better? Unless you want to abort your processing in the middle of your collection (like e.g. in find) foldLeft is considered a better way and it has slightly less boilerplate, but otherwise they are very similar.
I'm using ListBuffer here to avoid reversing lists.

Efficient and/or idiomatic way to turn Seq[Either[String, Int]] to (Seq[String], Seq[Int])

Slightly simplifying, my problem comes from a list of strings input that I want to parse with a function parse returning Either[String,Int].
Then list.map(parse) returns a list of Eithers. The next step in the program is to format an error message summing up all the errors or passing on the list of parsed integers.
Lets call the solution I'm looking for partitionEithers.
Calling
partitionEithers(List(Left("foo"), Right(1), Left("bar")))
Would give
(List("foo", "bar"),List(1))
Finding something like this in the standard library would be best. Failing that some kind of clean, idiomatic and efficient solution would be best. Also some kind of efficient utility function I could just paste into my projects would be ok.
I was very confused between these 3 earlier questions. As far as I can tell, neither of those questions matches my case, but some answers there seem to contain valid answers to this question.
Scala collections offer a partition function:
val eithers: List[Either[String, Int]] = List(Left("foo"), Right(1), Left("bar"))
eithers.partition(_.isLeft) match {
case (leftList, rightList) =>
(leftList.map(_.left.get), rightList.map(_.right.get))
}
=> res0: (List[String], List[Int]) = (List(foo, bar),List(1))
UPDATE
If you want to wrap it in a (maybe even somewhat type safer) generic function:
def partitionEither[Left : ClassTag, Right : ClassTag](in: List[Either[Left, Right]]): (List[Left], List[Right]) =
in.partition(_.isLeft) match {
case (leftList, rightList) =>
(leftList.collect { case Left(l: Left) => l }, rightList.collect { case Right(r: Right) => r })
}
You could use separate from MonadPlus (scalaz) or MonadCombine (cats) :
import scala.util.{Either, Left, Right}
import scalaz.std.list._
import scalaz.std.either._
import scalaz.syntax.monadPlus._
val l: List[Either[String, Int]] = List(Right(1), Left("error"), Right(2))
l.separate
// (List[String], List[Int]) = (List(error),List(1, 2))
I don't really get the amount of contortions of the other answers. So here is a one liner:
scala> val es:List[Either[Int,String]] =
List(Left(1),Left(2),Right("A"),Right("B"),Left(3),Right("C"))
es: List[Either[Int,String]] = List(Left(1), Left(2), Right(A), Right(B), Left(3), Right(C))
scala> es.foldRight( (List[Int](), List[String]()) ) {
case ( e, (ls, rs) ) => e.fold( l => ( l :: ls, rs), r => ( ls, r :: rs ) )
}
res5: (List[Int], List[String]) = (List(1, 2, 3),List(A, B, C))
Here is an imperative implementation mimicking the style of Scala collection internals.
I wonder if there should something like this in there, since at least I run into this from time to time.
import collection._
import generic._
def partitionEithers[L, R, E, I, CL, CR]
(lrs: I)
(implicit evI: I <:< GenTraversableOnce[E],
evE: E <:< Either[L, R],
cbfl: CanBuildFrom[I, L, CL],
cbfr: CanBuildFrom[I, R, CR])
: (CL, CR) = {
val ls = cbfl()
val rs = cbfr()
ls.sizeHint(lrs.size)
rs.sizeHint(lrs.size)
lrs.foreach { e => evE(e) match {
case Left(l) => ls += l
case Right(r) => rs += r
} }
(ls.result(), rs.result())
}
partitionEithers(List(Left("foo"), Right(1), Left("bar"))) == (List("foo", "bar"), List(1))
partitionEithers(Set(Left("foo"), Right(1), Left("bar"), Right(1))) == (Set("foo", "bar"), Set(1))
You can use foldLeft.
def f(s: Seq[Either[String, Int]]): (Seq[String], Seq[Int]) = {
s.foldRight((Seq[String](), Seq[Int]())) { case (c, r) =>
c match {
case Left(le) => (le +: r._1, r._2)
case Right(ri) => (r._1 , ri +: r._2)
}
}
}
val eithers: List[Either[String, Int]] = List(Left("foo"), Right(1), Left("bar"))
scala> f(eithers)
res0: (Seq[String], Seq[Int]) = (List(foo, bar),List(1))