def randomArray(length: Int, min: Int, max: Int) = {Write a code snippet that sets a to an array of n random integers between 0 (inclusive) and n (exclusive).
def randomArray(length: Int, min: Int, max: Int) = {Importing Random is not necessary, but shows how we can import something only in a block.
import scala.util.{Random => R}In case min > max, we cannot return an Int… So we use the useful sys.error to throw a RuntimeException with a meaningful message.
if (min >= max) sys.error("min should be < max")yield will gather all the results yielded inside the loop into a collection. Very useful !
Also, we can wrap the for statement into parentheses so that we can convert the result (a Vector by default) to an array
(for (_ <- 0 until length)
yield min + (R.nextDouble() * (max - min)).toInt
).toArray
}
randomArray(10, 10, 20) //> Array(11, 15, 14, 19, 15, 14, 19, 14, 16, 17)Write a loop that swaps adjacent elements of an array of integers. For example, Array(1, 2, 3, 4, 5) becomes Array(2, 1, 4, 3, 5).
Here, ensure you use Array and not List, as a list in scala is immutable.
def swap[T](array: Array[T]) = {
for (i <- 0 until array.length - 1 by 2) {
val temp = array(i)
array(i) = array(i + 1)
array(i + 1) = temp
}
array
}The swap is done in-place
var l1 = (0 to 10).toArray
swap(l1) //> Array(1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 10)but since the last statement of the swap method is array, the array is also returned, making the following work as well:
l1 = swap((0 to 10).toArray) //> Array(1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 10)Repeat the preceding assignment, but produce a new array with the swapped values. Use for/yield.
There are many possibilities. Here, I have two for loops, the second one permits me to traverse elements i-1 and i. Also, since we create a new object, an immutable list seems more appropriate.
def swapList[T](list: List[T]) = {
(for (i <- 1 until list.length + 1 by 2;
j <- (i - 1 to i reverse) if j < list.length)
yield j
).toList
}
swapList(0 to 10 toList) //> List(1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 10)Given an array of integers, produce a new array that contains all positive values of the original array, in their original order, followed by all values that are zero or negative, in their original order.
def positiveFirst1(list: List[Int]) = {
val pos = list.filter((_: Int) > 0)
val neg = list.filterNot((_: Int) > 0)
pos ++ neg
}Using for and yield:
def positiveFirst2(list: List[Int]) =
(for (elt <- list if elt > 0) yield elt) ++ (for(elt <- list if elt <= 0) yield elt)Testing the two codes:
val randomL = List(3, -5, 7, -4, 2, -10, -9, 0, 9, -10)
positiveFirst1(randomL) //> List(3, 7, 2, 9, -5, -4, -10, -9, 0, -10)
positiveFirst2(randomL) //> List(3, 7, 2, 9, -5, -4, -10, -9, 0, -10)def avg(list: List[Double]) = {
list.sum / list.length
}Testing:
avg({
for (i <- 0 to 10) yield scala.util.Random.nextDouble()
}.toList)How do you rearrange the elements of an Array[Int] so that they appear in reverse sorted order?
def reverseSort1(array : Array[Int]) = array.sorted.reversesortWith, the lambda should return true if a comes before b, false otherwise:def reverseSort2(array : Array[Int]) = array.sortWith(_ > _)sortBy, using the unary - to reverse the order:def reverseSort3(array : Array[Int]) = array.sortBy(-_)
var array = (0 to 10).toArray
reverseSort1(array)
reverseSort2(array)
reverseSort3(array)How do you do the same with an ArrayBuffer[Int]? To use an
ArrayBuffer, we only need to change the method’s signature.
This is because the sort methods are implemented in scala.collection.SeqLike, which both Array and ArrayBuffer implement.
import scala.collection.mutable.ArrayBuffer
(0 to 10).toBuffer.asInstanceOf[ArrayBuffer[Int]].sortBy(-_)Write a code snippet that produces all values from an array with duplicates removed. (Hint: Look at Scaladoc.) Use the
distinctmethod ofscala.collection.SeqLike.
var dupl = (0 to 10) ++ (1 to 11)
dupl.distinctRewrite the example at the end of Section 3.4, “Transforming Arrays,” on page 34 using the drop method for dropping the index of the first match. Look the method up in Scaladoc.
dropdrops the n first elements of a sequence.
def dropNegButFirst(array: Array[Int]) = {
var idx = for (i <- array.indices if array(i) < 0) yield i
if (idx.length == 0)
array
else {
idx = idx.drop(1)
var buff = array.toBuffer
for (i <- idx.reverse) buff.remove(i)
buff.toArray
}
}
dropNegButFirst((1 :: 2 :: (-3) :: (-2) :: 0 :: Nil).toArray)Make a collection of all time zones returned by java.util.TimeZone.getAvailableIDs that are in America. Strip off the “America/“ prefix and sort the result.
def americanTz = {
for (tz <- java.util.TimeZone.getAvailableIDs
if tz.startsWith("America"))
yield tz.replace("America/", "")
}
americanTzImport java.awt.datatransfer._ and make an object of type SystemFlavorMap with the call
val flavors = SystemFlavorMap.getDefaultFlavorMap().asInstanceOf[SystemFlavorMap]
Then call the getNativesForFlavor method with parameter DataFlavor.imageFlavor and get the return value as a Scala buffer. (Why this obscure class? It’s hard to find uses of java.util.List in the standard Java library.)
The getNativesForFlavor returns a java.util.List
import java.awt.datatransfer._
val flavors = SystemFlavorMap.getDefaultFlavorMap().asInstanceOf[SystemFlavorMap]
var javaList = flavors.getNativesForFlavor(DataFlavor.imageFlavor) // java.util.List[String] = [PNG, JFIF, TIFF]We can use the toArray and toBuffer methods, which seem to work:
javaList.toArray.toBuffer // scala.collection.mutable.Buffer[Object] = ArrayBuffer(PNG, JFIF, TIFF)We can also use the (now deprecated) JavaConversions util:
collection.JavaConversions.asScalaBuffer(javaList) // scala.collection.mutable.Buffer[String] = Buffer(PNG, JFIF, TIFF)The scala 2.12 way would be:
scala.collection.JavaConverters.asScalaBuffer(javaList) // scala.collection.mutable.Buffer[String] = Buffer(PNG, JFIF, TIFF)