Using pattern matching to swap two elements in scala - scala

I would like to use the pattern matching to swap the first two elements of an array, my code as shown below:
>scala val arr = Array(1,2,3,4,5)
>arr match { case Array(a,b,rest # _*) => Array(b,a,rest)
// Array(2,1,Vector(3,4,5))
However, the result should be Array(2,1,3,4,5). How to revise it?

Your problem is not passing in rest as a varargs, which is done using rest: _* syntax. This tells the compiler to pass in the collection methods as varargs, it works with Seq.
val arr = Array(1, 2, 3, 4, 5)
arr match { case Array(a, b, rest # _*) => Array(b, a +: rest: _*) }
There's an Array.apply method than takes a first element followed by a varargs, but there's none to pass in two elements and then varargs. Because of that, we need to prepend the second element to the Seq before passing the whole thing as varargs.
That's why we end up with a +: rest: _*. +: are invoked on the right hand side of the expression, so the method +: is defined on Seq, by convention Scala methods that end with : are right associative.

Related

Scala pattern match not working on Stream?

I do a group-by and I get key -> Stream(of values)
I then need to do a pattern match on the stream collection to access the last item
but the pattern match doesn't work.
When I manually build the list of values using Seq the same pattern match code works
So my question is there a way to convert the Stream to Seq or List?
The IDE says toSeq is redundant
When I manually build the list of values using Seq the same pattern match code works
In scala 2.12, Seq (or sequence) are defaulted to List, see this question:
scala> Seq(1,2,3)
res3: Seq[Int] = List(1, 2, 3)
This is probably why the pattern matching works on your sequence (which happens to be a List) but not an a Stream, see this question.
The IDE says toSeq is redundant
Stream are indeed Seq:
Stream(1,2,3).toSeq
res4: collection.immutable.Seq[Int] = Stream(1, 2, 3)
So my question is there a way to convert the Stream to Seq or List?
To transform a Stream into a List, you can call the .toList method:
Stream(1,2,3).toList
res5: List[Int] = List(1, 2, 3)
Or with this Answer you don't have to transform to List:
val n: Seq[Any] = Stream(..)
n match {
case Nil => "Empty"
case h :: t => "Non-empty"
case h #:: t => "Non-empty stream"
}
For Stream, the concat symbol should be #::, the pattern match should like:
Make sure you reverse the Stream - so you get the last element, here an example:
n.reverse match {
case Nil => "Empty"
case h #:: _ => s"last element is $h"
}
Check it here ScalaFiddle

can anyone explain what # _* mean in this code snippet? [duplicate]

This question already has answers here:
What does param: _* mean in Scala?
(3 answers)
Closed 4 years ago.
def swapElementsOfArray(array: Array[Int]) =
array match {
case Array(x, y, z # _*) => Array(y, x) ++ z
case _ => array
}
I don't get how # _* is used here. can anyone help to explain that? thank you in advance.
The operator _* makes reference to a sequence of elements, in your case, it'd be the "tail" of the array.
The operator # allows you to bind a matched pattern to a variable, in your case "z"
So with z # _* you are assigning to Z the rest of the array you are not using but you need to refer to it later.
val a= Array(2, 1, 3, 5, 3, 2)
def swapElementsOfArray(array: Array[Int]) =
array match {
case Array(x, y, z # _*) => Array(y, x) ++ z
case _ => array
}
swapElementsOfArray(a).toString
res0: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3, 5, 3, 2
z would be "3,5,3,2" you don't need it for use but you need the reference.
In this specific example _* means "the rest of the array".
The z # part is standard pattern match syntax for binding a variable name to a pattern
Please note that the _* operator is a general operator that applies to any vararg parameter, and it's sometimes referred to as the "splat operator".
You can read about it in the specification: https://www.scala-lang.org/files/archive/spec/2.11/04-basic-declarations-and-definitions.html#repeated-parameters
Here's the relevant sentence:
The only exception to this rule is if the last argument is marked to be a sequence argument via a _* type annotation. If m above is applied to arguments (e1,…,en,e′: _*), then the type of m in that application is taken to be (p1:T1,…,pn:Tn,ps:scala.Seq[S])
This applies to both matching and passing varargs. For example, the splat operator can be used to pass a sequence where a vararg is expected.
Example:
val s = Seq(1, 2, 3)
val a1 = Array(s) // does not compile
val a2 = Array(s: _*) // compiles, s is passed as vararg
a2 match {
case Array(s # _*) => s // s now contains all the elements of a2
}
a2 match {
case Array(head, tail # _*) => head // tail contains all the elements except the first
case _ => ??? // empty list!
}

Appending to a list pattern matching

I am currently facing the following issue.
I have code that essentially has the following cases:
val toList = this.toString.match {
case "" => List[MyType]()
case _ => this.val :: this.prev.toList
}
Obviously not exact but its the general gist. It works fine but I want the values appended to the list in the reverse order. Is there any good way to do this? Intellij throws errors if I try to reverse the order and do
this.prev.toList :: this.val
and also if I try to use operations like ++. Is what I'm trying to do impossible based on the structure of my class?
The specific errors I get involve "cannot resolve ::" or whatever symbol I use when I try to put this.prev.toList before this.val.
And yes the "this" aren't necessary- I included it to hopefully make my problem easier to understand.
:: adds an element at the beginning of this list
scala> 1 :: List(2,3)
List(1, 2, 3)
+: is the equivalent of ::
scala> 1 +: List(2,3)
List(1, 2, 3)
:+ append element at the end of the list
scala> List(1,2) :+ 3
List(1, 2, 3)
However the cost of prepending on List is O(1) but the appending one is O(n)!
For "numerous" collections you could consider other datastructure like Vector:
Vector provides very fast append and prepend
http://www.scala-lang.org/api/2.11.7/index.html#scala.collection.immutable.Vector
You can append with this method :+:
this.prev.toList :+ this.val // is `val` really then name?
But keep in mind that appending to a List can be very inefficient for long lists.

How can I functionally iterate over a collection combining elements?

I have a sequence of values of type A that I want to transform to a sequence of type B.
Some of the elements with type A can be converted to a B, however some other elements need to be combined with the immediately previous element to produce a B.
I see it as a small state machine with two states, the first one handling the transformation from A to B when just the current A is needed, or saving A if the next row is needed and going to the second state; the second state combining the saved A with the new A to produce a B and then go back to state 1.
I'm trying to use scalaz's Iteratees but I fear I'm overcomplicating it, and I'm forced to return a dummy B when the input has reached EOF.
What's the most elegant solution to do it?
What about invoking the sliding() method on your sequence?
You might have to put a dummy element at the head of the sequence so that the first element (the real head) is evaluated/converted correctly.
If you map() over the result from sliding(2) then map will "see" every element with its predecessor.
val input: Seq[A] = ??? // real data here (no dummy values)
val output: Seq[B] = (dummy +: input).sliding(2).flatMap(a2b).toSeq
def a2b( arg: Seq[A] ): Seq[B] = {
// arg holds 2 elements
// return a Seq() of zero or more elements
}
Taking a stab at it:
Partition your list into two lists. The first is the one you can directly convert and the second is the one that you need to merge.
scala> val l = List("String", 1, 4, "Hello")
l: List[Any] = List(String, 1, 4, Hello)
scala> val (string, int) = l partition { case s:String => true case _ => false}
string: List[Any] = List(String, Hello)
int: List[Any] = List(1, 4)
Replace the logic in the partition block with whatever you need.
After you have the two lists, you can do whatever you need to with your second using something like this
scala> string ::: int.collect{case i:Integer => i}.sliding(2).collect{
| case List(a, b) => a+b.toString}.toList
res4: List[Any] = List(String, Hello, 14)
You would replace the addition with whatever your aggregate function is.
Hopefully this is helpful.

Get item in the list in Scala?

How in the world do you get just an element at index i from the List in scala?
I tried get(i), and [i] - nothing works. Googling only returns how to "find" an element in the list. But I already know the index of the element!
Here is the code that does not compile:
def buildTree(data: List[Data2D]):Node ={
if(data.length == 1){
var point:Data2D = data[0] //Nope - does not work
}
return null
}
Looking at the List api does not help, as my eyes just cross.
Use parentheses:
data(2)
But you don't really want to do that with lists very often, since linked lists take time to traverse. If you want to index into a collection, use Vector (immutable) or ArrayBuffer (mutable) or possibly Array (which is just a Java array, except again you index into it with (i) instead of [i]).
Safer is to use lift so you can extract the value if it exists and fail gracefully if it does not.
data.lift(2)
This will return None if the list isn't long enough to provide that element, and Some(value) if it is.
scala> val l = List("a", "b", "c")
scala> l.lift(1)
Some("b")
scala> l.lift(5)
None
Whenever you're performing an operation that may fail in this way it's great to use an Option and get the type system to help make sure you are handling the case where the element doesn't exist.
Explanation:
This works because List's apply (which sugars to just parentheses, e.g. l(index)) is like a partial function that is defined wherever the list has an element. The List.lift method turns the partial apply function (a function that is only defined for some inputs) into a normal function (defined for any input) by basically wrapping the result in an Option.
Why parentheses?
Here is the quote from the book programming in scala.
Another important idea illustrated by this example will give you insight into why arrays are accessed with parentheses in Scala. Scala has fewer special cases than Java. Arrays are simply instances of classes like any other class in Scala. When you apply parentheses surrounding one or more values to a variable, Scala will transform the code into an invocation of a method named apply on that variable. So greetStrings(i) gets transformed into greetStrings.apply(i). Thus accessing an element of an array in Scala is simply a method call like any other. This principle is not restricted to arrays: any application of an object to some arguments in parentheses will be transformed to an apply method call. Of course this will compile only if that type of object actually defines an apply method. So it's not a special case; it's a general rule.
Here are a few examples how to pull certain element (first elem in this case) using functional programming style.
// Create a multdimension Array
scala> val a = Array.ofDim[String](2, 3)
a: Array[Array[String]] = Array(Array(null, null, null), Array(null, null, null))
scala> a(0) = Array("1","2","3")
scala> a(1) = Array("4", "5", "6")
scala> a
Array[Array[String]] = Array(Array(1, 2, 3), Array(4, 5, 6))
// 1. paratheses
scala> a.map(_(0))
Array[String] = Array(1, 4)
// 2. apply
scala> a.map(_.apply(0))
Array[String] = Array(1, 4)
// 3. function literal
scala> a.map(a => a(0))
Array[String] = Array(1, 4)
// 4. lift
scala> a.map(_.lift(0))
Array[Option[String]] = Array(Some(1), Some(4))
// 5. head or last
scala> a.map(_.head)
Array[String] = Array(1, 4)
Please use parentheses () to access the list of elements, as shown below.
list_name(index)