Looping through a list of tuples in Scala - scala

I have a sample List as below
List[(String, Object)]
How can I loop through this list using for?
I want to do something like
for(str <- strlist)
but for the 2d list above. What would be placeholder for str?

Here it is,
scala> val fruits: List[(Int, String)] = List((1, "apple"), (2, "orange"))
fruits: List[(Int, String)] = List((1,apple), (2,orange))
scala>
scala> fruits.foreach {
| case (id, name) => {
| println(s"$id is $name")
| }
| }
1 is apple
2 is orange
Note: The expected type requires a one-argument function accepting a 2-Tuple.
Consider a pattern matching anonymous function, { case (id, name) => ... }
Easy to copy code:
val fruits: List[(Int, String)] = List((1, "apple"), (2, "orange"))
fruits.foreach {
case (id, name) => {
println(s"$id is $name")
}
}

With for you can extract the elements of the tuple,
for ( (s,o) <- list ) yield f(s,o)

I will suggest using map, filter,fold or foreach(whatever suits your need) rather than iterating over a collection using loop.
Edit 1:
e.g
if you want to apply some func foo(tuple) on each element
val newList=oldList.map(tuple=>foo(tuple))
val tupleStrings=tupleList.map(tuple=>tuple._1) //in your situation
if you want to filter according to some boolean condition
val newList=oldList.filter(tuple=>someCondition(tuple))
or simply if you want to print your List
oldList.foreach(tuple=>println(tuple)) //assuming tuple is printable
you can find example and similar functions here https://twitter.github.io/scala_school/collections.html

If you just want to get the strings you could map over your list of tuples like this:
// Just some example object
case class MyObj(i: Int = 0)
// Create a list of tuples like you have
val tuples = Seq(("a", new MyObj), ("b", new MyObj), ("c", new MyObj))
// Get the strings from the tuples
val strings = tuples.map(_._1)
// Output: Seq[String] = List(a, b, c)
Note: Tuple members are accessed using the underscore notation (which
is indexed from 1, not 0)

Related

Scala - Getting sequence id of elements during map

Scala newbie question.
I want to map a list to another list but I want to every object to know its sequence number.
In the following simple code, what is the right alternative to the usage of var v?
class T (s: String, val sequence:Int)
val stringList = List("a","b","C")
var v = 0
val tList = stringList.map(s => { v=v+1; new T(s, v);})
You can use zipWithIndex to get a tuple for each element containing the actual element and the index, then just map that tuple to your object:
List("a", "b", "C")
.zipWithIndex
.map(e => new T(e._1, e._2))
val tList = List.tabulate(stringList.length)(idx => new T(stringList(idx), idx))

How to find tuple with different value in a list using scala?

I have following list:
val list = List(("name1",20),("name2",20),("name1",30),("name2",30),
("name3",40),("name3",30),("name3",20))
I want following output:
List(("name3",40))
I tried following:
val distElements = list.map(_._2).distinct
list.groupBy(_._1).map{ case(k,v) =>
val h = v.map(_._2)
if(distElements.equals(h)) List.empty else distElements.diff(h)
}.flatten
But this is not I am looking for.
Can anybody give answer/hint me to get expected output.
I understand the question as looking for the element of the list whose _2 (number) occurs only once.
val list = List(("name1",20),("name2",20),("name1",30),("name2",30),
("name3",40),("name3",30),("name3",20))
First you group by the _2 element, which gives you a map whose keys are lists of all elements with the same _2:
val g = list.groupBy(_._2) // Map[Int, List[(String, Int)]]
Now you can filter those entries that consists only of one element:
val opt = g.collectFirst { // Option[(String, Int)]
case (_, single :: Nil) => single
}
Or (if you are expecting possibly more than one distinct value)
val col = g.collect { // Map[String, Int]
case (_, single :: Nil) => single
}
Seems to me that you're looking to match against both the value of the left hand and the right hand at the same time while also preserving the type of collection you're looking at, a List. I would use collect:
val out = myList.collect{
case item # ("name3", 40) => item
}
which combines a PartialFunction with filter and map like qualities. In this case, it filters out any value for which the PartialFunction is not defined while mapping the values which match. Here, I've only allowed for a singular match.

Scala Tuple to String (using mkString)

Suppose I have a list of tuples
('a', 1), ('b', 2)...
How would one get about converting it to a String in the format
a 1
b 2
I tried using collection.map(_.mkString('\t')) However I'm getting an error since essentially I'm applying the operation to a tuple instead of a list. Using flatMap didn't help either
For Tuple2 you can use:
val list = List(("1", 4), ("dfg", 67))
list.map { case (str, int) => s"$str $int"}
For any tuples try this code:
val list = List[Product](("dfsgd", 234), ("345345", 345, 456456))
list.map { tuple =>
tuple.productIterator.mkString("\t")
}

How to turn a list of objects into a map of two fields in Scala

I'm having a real brain fart here. I'm working with the Play Framework. I have a method which takes a map and turns it into a HTML select element. I had a one-liner to take a list of objects and convert it into a map of two of the object's fields, id and name. However, I'm a Java programmer and my Scala is weak, and I've only gone and forgotten the syntax of how I did it.
I had something like
organizations.all.map {org => /* org.prop1, org.prop2 */ }
Can anyone complete the commented part?
I would suggest:
map { org => (org.id, org.name) } toMap
e.g.
scala> case class T(val a : Int, val b : String)
defined class T
scala> List(T(1, "A"), T(2, "B"))
res0: List[T] = List(T(1,A), T(2,B))
scala> res0.map(t => (t.a, t.b))
res1: List[(Int, String)] = List((1,A), (2,B))
scala> res0.map(t => (t.a, t.b)).toMap
res2: scala.collection.immutable.Map[Int,String] = Map(1 -> A, 2 -> B)
You could also take an intermediary List out of the equation and go straight to the Map like this:
case class Org(prop1:String, prop2:Int)
val list = List(Org("foo", 1), Org("bar", 2))
val map:Map[String,Int] = list.map(org => (org.prop1, org.prop2))(collection.breakOut)
Using collection.breakOut as the implicit CanBuildFrom allows you to basically skip a step in the process of getting a Map from a List.

generate case classes from CSV in Scala

I've got a CSV response from a service and I want to generate a list of case classes. For example:
case class MyCaseClass(e1: String, e2: String, e3: String)
val body = getLargeCsvFromServiceOrSomething()
val elements = body.split(",")
Now I have an Array[String]. I want to take that large array and break it down into 3 element chucks, so I can generate my List[MyCaseClass], where each instance take 3 elements from the array. Is there a method similar to splitAt, but spits every n elements? I'm sure I can do this point-free, but it's just not coming to me.
What you want is grouped:
scala> List(1,2,3,4,5,6,7).grouped(3).toList
res0: List[List[Int]] = List(List(1, 2, 3), List(4, 5, 6), List(7))
So your thing might be like:
val elements = Array("a","b","c","d","e","f")
val classes = elements.grouped(3).map{ case Array(a,b,c) => MyCaseClass(a,b,c) }
println(classes.toList) // List(MyCaseClass(a,b,c), MyCaseClass(d,e,f))