How to get max and min values of an Array of Tuples - scala

Say I have a List of Tuples of Integers
var i = Array(1->3, 5->9, 15->18)
How can I return a Tuple of the highest and lowest values from the above?
So for the above input, 1-> 18 should be returned as 1 is the lowest and 18 is the highest value. Here's the skeleton of the function that takes an Array of Tuples and returns the highest & the lowest values as a Tuple.
def returnHighest(i: Array[(Int, Int)]): (Int, Int)={
....
}

Lot's of ways to do this of course. Here is one:
val i = Array(1->3, 5->9, 15->18)
i: Array[(Int, Int)] = Array((1,3), (5,9), (15,18))
scala> val flatI = i.flatMap{case(a,b) => List(a, b)}
flatI: Array[Int] = Array(1, 3, 5, 9, 15, 18)
scala> flatI.min -> flatI.max
res3: (Int, Int) = (1,18)

You could use foldLeft, but you need to be careful about the start value. What if the array is empty ?
val res4 = Array(1->3, 5->9, 15->18)
res4.foldLeft(res4(0))({
case (acc, i) =>
Math.min(acc._1, i._1) -> Math.max(acc._2, i._2)
})
res6: (Int, Int) = (1, 18)

Related

scala: find the amount of a specific element in a list

I want to write a function count: (List[Int]) => Int in scala which counts the amount of a specific element in a list. I want to implement it this way:
count(2, List(2, 4, 5, 2, 2, 7))
should return 3. How can I do this in scala?
List has an inbuilt count already like #Jeffery mentioned.
You asked to make it a function, so:
scala> val count = (x: Int, ls: List[Int]) => ls.count(_ == x)
count: (Int, List[Int]) => Int = <function2>
scala> count(2, List(2,4,5,2,2,7))
res1: Int = 3

How to calculate length of string in a tuple in scala

Given a list of tuples, where the 1st element of the tuple is an integer and the second element is a string,
scala> val tuple2 : List[(Int,String)] = List((1,"apple"),(2,"ball"),(3,"cat"),(4,"doll"),(5,"eggs"))
tuple2: List[(Int, String)] = List((1,apple), (2,ball), (3,cat), (4,doll), (5,eggs))
I want to print the numbers where the corresponding string length is 4.
Can this be done in one line ?
you need .collect which is filter+map
given your input,
scala> val input : List[(Int,String)] = List((1,"apple"),(2,"ball"),(3,"cat"),(4,"doll"),(5,"eggs"))
input: List[(Int, String)] = List((1,apple), (2,ball), (3,cat), (4,doll), (5,eggs))
filter those of length 4,
scala> input.collect { case(number, string) if string.length == 4 => number}
res2: List[Int] = List(2, 4, 5)
alternative solution using filter + map,
scala> input.filter { case(number, string) => string.length == 4 }
.map { case (number, string) => number}
res4: List[Int] = List(2, 4, 5)
you filter and print as below
tuple2.filter(_._2.length == 4).foreach(x => println(x._1))
You should have output as
2
4
5
I like #prayagupd answer using collect. But foldLeft is the one of my favourite function in Scala! you can use foldLeft:
scala> val input : List[(Int,String)] = List((1,"apple"),(2,"ball"),(3,"cat"),(4,"doll"),(5,"eggs"))
input: List[(Int, String)] = List((1,apple), (2,ball), (3,cat), (4,doll), (5,eggs))
scala> input.foldLeft(List.empty[Int]){case (acc, (n,str)) => if(str.length ==4) acc :+ n else acc}
res3: List[Int] = List(2, 4, 5)
Using a for comprehension as follows,
for ((i,s) <- tuple2 if s.size == 4) yield i
which for the example above delivers
List(2, 4, 5)
Note we pattern match and extract the elements in each tuple and filter by string size. To print a list consider for instance aList.foreach(println).
This will do:
tuple2.filter(_._2.size==4).map(_._1)
In Scala REPL:
scala> val tuple2 : List[(Int,String)] = List((1,"apple"),(2,"ball"),(3,"cat"),(4,"doll"),(5,"eggs"))
tuple2: List[(Int, String)] = List((1,apple), (2,ball), (3,cat), (4,doll), (5,eggs))
scala> tuple2.filter(_._2.size==4).map(_._1)
res261: List[Int] = List(2, 4, 5)
scala>

Reduce by inspecting tuple element

I want to find the Tuple with the largest second element:
mylist.reduce { (x, y) => {
if (y._1 > x._1) y
else x
}}
Where x and y are of type Tuple3[DenseVector[Int], Double, PipelineModel].
I get the error that > cannot be resolved. What's up with that? Using foldLeft and providing a zero element did not help either.
Can I write the code nicer? (It doesn't look so nice, I think.)
In a triplet (a, b, c) triplet._2 gives you the second element.
_1 gives first element
_2 gives second element
_3 gives third element
Tuples are not zero based.
scala> val triplet = (1, 2, 3)
triplet: (Int, Int, Int) = (1,2,3)
scala> triplet._1
res0: Int = 1
scala> triplet._2
res1: Int = 2
scala> triplet._3
res2: Int = 3
Answer 1:
In your case triplet._1 gives the first element of the triplet (tuple3) which is DenseVector[Int] element on which you cannot use >. Thats why > is not resolved.
Answer 2:
maxBy
l.maxBy(_._2)
Scala REPL
scala> val l = List((1, 2, 3), (0, 0, 1))
l: List[(Int, Int, Int)] = List((1,2,3), (0,0,1))
scala> l.maxBy(_._2)
res1: (Int, Int, Int) = (1,2,3)
Reduce
l.reduce { (x, y) => if (x._2 > y._2) x else y }
Scala REPL
scala> val l = List((1, 2, 3), (0, 0, 1))
l: List[(Int, Int, Int)] = List((1,2,3), (0,0,1))
scala> l.reduce { (x, y) => if (x._2 > y._2) x else y }
res3: (Int, Int, Int) = (1,2,3)

How can I find the index of the maximum value in a List in Scala?

For a Scala List[Int] I can call the method max to find the maximum element value.
How can I find the index of the maximum element?
This is what I am doing now:
val max = list.max
val index = list.indexOf(max)
One way to do this is to zip the list with its indices, find the resulting pair with the largest first element, and return the second element of that pair:
scala> List(0, 43, 1, 34, 10).zipWithIndex.maxBy(_._1)._2
res0: Int = 1
This isn't the most efficient way to solve the problem, but it's idiomatic and clear.
Since Seq is a function in Scala, the following code works:
list.indices.maxBy(list)
even easier to read would be:
val g = List(0, 43, 1, 34, 10)
val g_index=g.indexOf(g.max)
def maxIndex[ T <% Ordered[T] ] (list : List[T]) : Option[Int] = list match {
case Nil => None
case head::tail => Some(
tail.foldLeft((0, head, 1)){
case ((indexOfMaximum, maximum, index), elem) =>
if(elem > maximum) (index, elem, index + 1)
else (indexOfMaximum, maximum, index + 1)
}._1
)
} //> maxIndex: [T](list: List[T])(implicit evidence$2: T => Ordered[T])Option[Int]
maxIndex(Nil) //> res0: Option[Int] = None
maxIndex(List(1,2,3,4,3)) //> res1: Option[Int] = Some(3)
maxIndex(List("a","x","c","d","e")) //> res2: Option[Int] = Some(1)
maxIndex(Nil).getOrElse(-1) //> res3: Int = -1
maxIndex(List(1,2,3,4,3)).getOrElse(-1) //> res4: Int = 3
maxIndex(List(1,2,2,1)).getOrElse(-1) //> res5: Int = 1
In case there are multiple maximums, it returns the first one's index.
Pros:You can use this with multiple types, it goes through the list only once, you can supply a default index instead of getting exception for empty lists.
Cons:Maybe you prefer exceptions :) Not a one-liner.
I think most of the solutions presented here go thru the list twice (or average 1.5 times) -- Once for max and the other for the max position. Perhaps a lot of focus is on what looks pretty?
In order to go thru a non empty list just once, the following can be tried:
list.foldLeft((0, Int.MinValue, -1)) {
case ((i, max, maxloc), v) =>
if (v > max) (i + 1, v, i)
else (i + 1, max, maxloc)}._3
Pimp my library! :)
class AwesomeList(list: List[Int]) {
def getMaxIndex: Int = {
val max = list.max
list.indexOf(max)
}
}
implicit def makeAwesomeList(xs: List[Int]) = new AwesomeList(xs)
//> makeAwesomeList: (xs: List[Int])scalaconsole.scratchie1.AwesomeList
//Now we can do this:
List(4,2,7,1,5,6) getMaxIndex //> res0: Int = 2
//And also this:
val myList = List(4,2,7,1,5,6) //> myList : List[Int] = List(4, 2, 7, 1, 5, 6)
myList getMaxIndex //> res1: Int = 2
//Regular list methods also work
myList filter (_%2==0) //> res2: List[Int] = List(4, 2, 6)
More details about this pattern here: http://www.artima.com/weblogs/viewpost.jsp?thread=179766

Simple question about tuple of scala

I'm new to scala, and what I'm learning is tuple.
I can define a tuple as following, and get the items:
val tuple = ("Mike", 40, "New York")
println("Name: " + tuple._1)
println("Age: " + tuple._2)
println("City: " + tuple._3)
My question is:
How to get the length of a tuple?
Is tuple mutable? Can I modify its items?
Is there any other useful operation we can do on a tuple?
Thanks in advance!
1] tuple.productArity
2] No.
3] Some interesting operations you can perform on tuples: (a short REPL session)
scala> val x = (3, "hello")
x: (Int, java.lang.String) = (3,hello)
scala> x.swap
res0: (java.lang.String, Int) = (hello,3)
scala> x.toString
res1: java.lang.String = (3,hello)
scala> val y = (3, "hello")
y: (Int, java.lang.String) = (3,hello)
scala> x == y
res2: Boolean = true
scala> x.productPrefix
res3: java.lang.String = Tuple2
scala> val xi = x.productIterator
xi: Iterator[Any] = non-empty iterator
scala> while(xi.hasNext) println(xi.next)
3
hello
See scaladocs of Tuple2, Tuple3 etc for more.
One thing that you can also do with a tuple is to extract the content using the match expression:
def tupleview( tup: Any ){
tup match {
case (a: String, b: String) =>
println("A pair of strings: "+a + " "+ b)
case (a: Int, b: Int, c: Int) =>
println("A triplet of ints: "+a + " "+ b + " " +c)
case _ => println("Unknown")
}
}
tupleview( ("Hello", "Freewind"))
tupleview( (1,2,3))
Gives:
A pair of strings: Hello Freewind
A triplet of ints: 1 2 3
Tuples are immutable, but, like all cases classes, they have a copy method that can be used to create a new Tuple with a few changed elements:
scala> (1, false, "two")
res0: (Int, Boolean, java.lang.String) = (1,false,two)
scala> res0.copy(_2 = true)
res1: (Int, Boolean, java.lang.String) = (1,true,two)
scala> res1.copy(_1 = 1f)
res2: (Float, Boolean, java.lang.String) = (1.0,true,two)
Concerning question 3:
A useful thing you can do with Tuples is to store parameter lists for functions:
def f(i:Int, s:String, c:Char) = s * i + c
List((3, "cha", '!'), (2, "bora", '.')).foreach(t => println((f _).tupled(t)))
//--> chachacha!
//--> borabora.
[Edit] As Randall remarks, you'd better use something like this in "real life":
def f(i:Int, s:String, c:Char) = s * i + c
val g = (f _).tupled
List((3, "cha", '!'), (2, "bora", '.')).foreach(t => println(g(t)))
In order to extract the values from tuples in the middle of a "collection transformation chain" you can write:
val words = List((3, "cha"),(2, "bora")).map{ case(i,s) => s * i }
Note the curly braces around the case, parentheses won't work.
Another nice trick ad question 3) (as 1 and 2 are already answered by others)
val tuple = ("Mike", 40, "New York")
tuple match {
case (name, age, city) =>{
println("Name: " + name)
println("Age: " + age)
println("City: " + city)
}
}
Edit: in fact it's rather a feature of pattern matching and case classes, a tuple is just a simple example of a case class...
You know the size of a tuple, it's part of it's type. For example if you define a function def f(tup: (Int, Int)), you know the length of tup is 2 because values of type (Int, Int) (aka Tuple2[Int, Int]) always have a length of 2.
No.
Not really. Tuples are useful for storing a fixed amount of items of possibly different types and passing them around, putting them into data structures etc. There's really not much you can do with them, other than creating tuples, and getting stuff out of tuples.
1 and 2 have already been answered.
A very useful thing that you can use tuples for is to return more than one value from a method or function. Simple example:
// Get the min and max of two integers
def minmax(a: Int, b: Int): (Int, Int) = if (a < b) (a, b) else (b, a)
// Call it and assign the result to two variables like this:
val (x, y) = minmax(10, 3) // x = 3, y = 10
Using shapeless, you easily get a lot of useful methods, that are usually available only on collections:
import shapeless.syntax.std.tuple._
val t = ("a", 2, true, 0.0)
val first = t(0)
val second = t(1)
// etc
val head = t.head
val tail = t.tail
val init = t.init
val last = t.last
val v = (2.0, 3L)
val concat = t ++ v
val append = t :+ 2L
val prepend = 1.0 +: t
val take2 = t take 2
val drop3 = t drop 3
val reverse = t.reverse
val zip = t zip (2.0, 2, "a", false)
val (unzip, other) = zip.unzip
val list = t.toList
val array = t.toArray
val set = t.to[Set]
Everything is typed as one would expect (that is first has type String, concat has type (String, Int, Boolean, Double, Double, Long), etc.)
The last method above (.to[Collection]) should be available in the next release (as of 2014/07/19).
You can also "update" a tuple
val a = t.updatedAt(1, 3) // gives ("a", 3, true, 0.0)
but that will return a new tuple instead of mutating the original one.