sequence

How to use Scala’s sortInPlaceBy method on mutable sequences (ArrayBuffer, ArrayDeque)

Table of Contents1 - Reading the Scaladoc2 - How I think sortInPlaceBy works3 - A sortInPlaceBy example4 - A second example5 - Discussion6 - Summary

When I first looked at the sortInPlaceBy method that was introduced on mutable sequences in Scala 2.13, I couldn’t figure out exactly what it was supposed to do.

Unable to find any examples of “scala sortInPlaceBy” on planet Earth this evening (February 23, 2020), I had to resort to some actual work, and looked at the Scaladoc.

Back to top

Reading the Scaladoc

This is what I see when I look at the Scaladoc for sortInPlaceBy on the ArrayBuffer:

def sortInPlaceBy[B](f: (A) => B)(implicit ord: Ordering[B]): ArrayBuffer.this.type

You can’t see by looking at that method what A is, so I scrolled up to the top of the page and saw this at the beginning of the Scaladoc:

How to create a large test Map in Scala (converting a sequence to a map)

If you ever need to create a large test Scala Map, I just used this approach and it worked fine:

val map = (for (i <- 1 to 5_000_000) yield (i, 10*i)).toMap

The initial results in the Scala REPL look like this:

val map: Map[Int, Int] = HashMap(4584205 -> 45842050, 2231874 -> 22318740, ...

The code works by creating a series of tuples with the yield expression, where each key is i, and each value is 10*i. Here are a couple of other ways to convert a Scala sequence to a map:

val map = Vector.range(0,1_000_000).map(i => (i, i*10)).toMap
val map = Vector.range(0,1_000_000).map(i => i -> i*10).toMap

How to drop the first matching element in a Scala sequence

Summary: This blog post shows one way to drop/filter the first matching element from a Scala sequence (Seq, List, Vector, Array, etc.). I don’t claim that the algorithm is efficient, but it does work.

Background

While creating some Scala test code earlier today I had an immutable list of toppings for a pizza, and I got into a situation where I wanted to remove the first instance of a topping.

A Scala method to write a list of strings to a file

As a brief note today, here’s a Scala method that writes the strings in a list — more accurately, a Seq[String] — to a file:

def writeFile(filename: String, lines: Seq[String]): Unit = {
    val file = new File(filename)
    val bw = new BufferedWriter(new FileWriter(file))
    for (line <- lines) {
        bw.write(line)
    }
    bw.close()
}

Scala: Generating a sequence/list of all ASCII printable characters

I ran into a couple of interesting things today when trying to generate random alphanumeric strings in Scala, which can be summarized like this. I won’t get into the “random” stuff I was working on, but here are a couple of examples of how to generate lists of alphanumeric/ASCII characters in Scala:

scala> val chars = ('a' to 'Z').toList
chars: List[Char] = List()

scala> val chars = ('A' to 'z').toList
chars: List[Char] = 
List(A, B, C, D, E, F, G, H, I, J, K, L, 
     M, N, O, P, Q, R, S, T, U, V, W, X, 
     Y, Z, [, \, ], ^, _, `, a, b, c, d, 
     e, f, g, h, i, j, k, l, m, n, o, p, 
     q, r, s, t, u, v, w, x, y, z)

scala> val chars = (' ' to 'z').toList
chars: List[Char] = 
List( , !, ", #, $, %, &, ', (, ), *, +, 
     ,, -, ., /, 0, 1, 2, 3, 4, 5, 6, 7, 
     8, 9, :, ;, <, =, >, ?, @, A, B, C, 
     D, E, F, G, H, I, J, K, L, M, N, O, 
     P, Q, R, S, T, U, V, W, X, Y, Z, [, 
     \, ], ^, _, `, a, b, c, d, e, f, g, 
     h, i, j, k, l, m, n, o, p, q, r, s, 
     t, u, v, w, x, y, z)

Scala: Convert a String with newline characters to a sequence/list of strings

If you ever need a Scala method/function to convert a string with newline characters in it to a sequence of strings (Seq[String]), here you go:

def convertStringWithNewlinesToSeq(s: String): Seq[String] =
    s.split("\n").toVector

You can convert the final result to a Vector, Seq, List, ArrayBuffer, Array, etc., but I prefer Vector. The Scala REPL demonstrates how it works:

scala> convertStringWithNewlinesToSeq("")
res0: Seq[String] = Vector("")

scala> convertStringWithNewlinesToSeq("foo")
res1: Seq[String] = Vector(foo)

scala> convertStringWithNewlinesToSeq("foo\nbar\nbaz")
res2: Seq[String] = Vector(foo, bar, baz)

scala> convertStringWithNewlinesToSeq("foo\nbar\nbaz\n\n")
res3: Seq[String] = Vector(foo, bar, baz)

How to get multiple, unique, random elements from a list of elements

One thing I never thought about before is that if you need to get multiple, unique, random elements from a list of elements, one solution to the problem is to shuffle the list and then take as many elements as you want/need. For instance, if you want three unique, random elements from a list of integers in Scala, you can do this:

scala> val list = List(1,2,3,4,5,1,2,3,4,5)
list: List[Int] = List(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)

scala> val uniq = list.distinct
uniq: List[Int] = List(1, 2, 3, 4, 5)

scala> val shuffled = scala.util.Random.shuffle(uniq)
shuffled: List[Int] = List(1, 4, 5, 2, 3)

scala> val firstThree = shuffled.take(3)
firstThree: List[Int] = List(1, 4, 5)

As that solution shows, you start with a simple list; get the unique/distinct elements from the list; shuffle those elements to create a new list; then take the first three elements from the shuffled list. That’s probably not a great solution for huge lists, but for many simple lists it’s a way to get multiple random elements from the list.

Scala tip: How to extract a field from a sequence of objects to create a new sequence

As a brief Scala tip, a fun thing you can do with the map method on Scala sequences (Array, List, Seq, Vector, etc.) is to convert a sequence of objects into a sequence of something else, typically extracting a field from the original object to create the new sequence.

For instance, imagine that you have a case class named Person that has two constructor parameters, firstName and lastName:

A Scala ‘foldLeft’ function written using recursion alvin January 20, 2018 - 4:25pm

As a short note, here’s some Scala source code that shows how to write a foldLeft function using recursion: