map function in Scala clarification - scala

I am confused on how to write the map function, which maps over two lists:
for example:
def map[A,B,C](f: (A, B) => C, lst1: List[A], lst2: List[B]): List[C]
The input would be 2 lists and the output could be a list that adds the integers alternatively
Test example:
assert(map(add, List(1, 2, 3), List(4, 5, 6)) == List(5, 7, 9))

You could use f.tupled to convert f from a function that accepts to arguments (A, B) => C, to a function that accepts one argument as a tuple ((A, B)) => C. Then, you can zip the lists together (make them one list of tuples) and feed them to f using the traditional map.
def map[A,B,C](f: (A, B) => C, lst1: List[A], lst2: List[B]): List[C] =
(lst1 zip lst2) map f.tupled
scala> def add(a: Int, b: Int): Int = a + b
add: (a: Int, b: Int)Int
scala> map(add, List(1, 2, 3), List(4, 5, 6))
res20: List[Int] = List(5, 7, 9)
Keep in mind that if the two lists are not the same size, then zip will truncate the longer list to match the size of the smaller one.

As stated in m-z's answer you can zip the lists, and then map on the list of tuples. If you want to avoid the use of tupled, you can do the destructure explicitly:
def map[A,B,C](f: (A, B) => C, lst1: List[A], lst2: List[B]): List[C] = {
val zipped = lst1 zip lst2
zipped.map { case (a,b) => f(a,b) }
}

Related

SortedSet fold type mismatch

I have this code:
def distinct(seq: Seq[Int]): Seq[Int] =
seq.fold(SortedSet[Int]()) ((acc, i) => acc + i)
I want to iterate over seq, delete duplicates (keep the first number) and keep order of the numbers. My idea was to use a SortedSet as an acc.
But I am getting:
Type mismatch:
Required: String
Found: Any
How to solve this? (I also don't know how to convert SortedSet to Seq in the final iteration as I want distinct to return seq)
p.s. without using standard seq distinct method
Online code
You shouldn't use fold if you try to accumulate something with different type than container (SortedSet != Int) in your case. Look at signature fold:
def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1
it takes accumulator with type A1 and combiner function (A1, A1) => A1 which combines two A1 elements.
In your case is better to use foldLeft which takes accumulator with different type than container:
def foldLeft[B](z: B)(op: (B, A) => B): B
it accumulates some B value using seed z and combiner from B and A to B.
In your case I would like to use LinkedHashSet it keeps the order of added elements and remove duplicates, look:
import scala.collection.mutable
def distinct(seq: Seq[Int]): Seq[Int] = {
seq.foldLeft(mutable.LinkedHashSet.empty[Int])(_ + _).toSeq
}
distinct(Seq(7, 2, 4, 2, 3, 0)) // ArrayBuffer(7, 2, 4, 3, 0)
distinct(Seq(0, 0, 0, 0)) // ArrayBuffer(0)
distinct(Seq(1, 5, 2, 7)) // ArrayBuffer(1, 5, 2, 7)
and after folding just use toSeq
be careful, lambda _ + _ is just syntactic sugar for combiner:
(linkedSet, nextElement) => linkedSet + nextElement
I would just call distinct on your Seq. You can see in the source-code of SeqLike, that distinct will just traverse the Seq und skip already seen data:
def distinct: Repr = {
val b = newBuilder
val seen = mutable.HashSet[A]()
for (x <- this) {
if (!seen(x)) {
b += x
seen += x
}
}
b.result
}

Readable FoldRight via FoldLeft in Scala

In Functional Programming in Scala, the author asks to express FoldRight via FoldLeft. And then the author offers the following implementation:
def foldRightViaFoldLeftAuthor[A, B](l: List[A], z: B)(f: (A, B) => B): B = {
foldLeft(l, (b: B) => b)((g, a) => b => g(f(a, b)))(z)
}
There have been a couple of questions like this asking to explain the author's solution. And probably a lot of people are still struggling to understand it.
While I was thinking about the task I came up with a different implementation that seems much more readable and easier to grasp at least for me
def foldRightViaFoldLeftMy[A, B](l: List[A], z: B)(f: (A, B) => B): B = {
foldLeft(l, z)(((g: (A, B) => B) => (b: B, a: A) => g(a, b)) (f))
}
So I basically prepare a function that converts f(a,b) to f(b,a) and now I'm able to call foldLeft that is tail-recursive.
So my questions are:
Is there any reason to implement it in the way the author did?
Are there any drawbacks in my implementation in comparison to the author's?
You've written an implementation that has the same signature as foldRight, but it doesn't have the right semantics when the combination operation isn't commutative. To take one example, a right fold with the empty list as zero and cons as the combination operation should be identity:
scala> val input = List(1, 2, 3)
input: List[Int] = List(1, 2, 3)
scala> val f: (Int, List[Int]) => List[Int] = _ :: _
f: (Int, List[Int]) => List[Int] = $$Lambda$1912/991363637#5e9bf744
scala> foldRightViaFoldLeftAuthor(input, List.empty[Int])(f)
res0: List[Int] = List(1, 2, 3)
But your implementation reverses the list:
scala> foldRightViaFoldLeftMy(input, List.empty[Int])(f)
res1: List[Int] = List(3, 2, 1)
This is because you're still folding from left to right, even though you've switched the order of the combination function's arguments. I find the diagrams on the Wikipedia page about fold useful for visualizing the difference. In your implementation the applications happen like this:
scala> f(3, f(2, f(1, Nil)))
res2: List[Int] = List(3, 2, 1)
While in the book's implementation you have something like this:
((b3: List[Int]) =>
((b2: List[Int]) =>
((b1: List[Int]) => identity(f(1, b1)))(f(2, b2)))(f(3, b3)
)
)(Nil)
Which boils down to:
scala> f(1, f(2, f(3, Nil)))
res3: List[Int] = List(1, 2, 3)
So the answer to both of your questions is "yes", there is an important difference between your implementation and the book's.

scala: how scala converts foldLeft as currying function

Could someone explain how currying happens in foldLeft for the below example:
val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
>numbers: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val numberFunc = numbers.foldLeft(List[Int]())_
>numberFunc: ((List[Int], Int) => List[Int]) => List[Int]
My Understanding is:
(List[Int], Int) - (accumulator which in this case is empty List, each element of the numbers list)
=> List[Int] - which is the output numberFunc list.
=> List[Int] - what does this represent?
Thanks.
Step by step:
foldLeft on a List[A] has a signature foldLeft[B](b: B)(f: (B, A) => B): B
therefore, in general, for a list: List[A] and b: B, the curried expression list.foldLeft(b) _ would have type ((B, A) => B) => B
numbers has type List[Int], thus A is inferred to be Int
List[Int]() has type List[Int], thus B is inferred to be List[Int]
Substituting Int for A and List[Int] for B in ((B, A) => B) => B, you obtain (List[Int], Int) => List[Int]) => List[Int]. That's exactly what the compiler gives you.
In words:
(numberFunc : // `numberFunc` is a function that
( // given a function that
(List[Int], Int) // takes an accumulator and an int
=> // and produces
List[Int] // an updated list of ints
)
=> // produces
List[Int] // a list of ints
)

How to make a scala collection contain unique elements? ("unique" defined)

Say I have a list as follows:
val l = List( (1, 2, "hi"), (1, 3, "hello"), (2, 3, "world"), (1, 2, "hello") )
I want to make the elements of l distinct ignoring the 3rd element of the tuple. That is, two elements of l are considered same if their first two components are same.
So makeDistinct(l) should return
List( (1, 2, "hi"), (1, 3, "hello"), (2, 3, "world") )
What is the most Scala-like and generic way to do implement makeDistinct
EDIT: We are free to choose which to drop, and ordering need not be preserved.
If you want to do this with lists, use groupBy:
l.groupBy(x => (x._1, x._2)).map(kv => kv._2.head).toList
If you really want to be generic for all collection types:
scala> import scala.collection.generic.CanBuildFrom
import scala.collection.generic.CanBuildFrom
scala> def distinct[A, B, C, CC[X] <: Traversable[X]](xs: CC[(A, B, C)])(implicit cbf: CanBuildFrom[Nothing, (A, B, C), CC[(A, B, C)]]): CC[(A, B, C)] = xs.groupBy(x => (x._1, x._2)).map(kv => kv._2.head).to[CC]
warning: there were 1 feature warnings; re-run with -feature for details
distinct: [A, B, C, CC[X] <: Traversable[X]](xs: CC[(A, B, C)])(implicit cbf: scala.collection.generic.CanBuildFrom[Nothing,(A, B, C),CC[(A, B, C)]])CC[(A, B, C)]
scala> distinct(List((1, 2, "ok"), (1, 3, "ee"), (1, 2, "notok")))
res0: List[(Int, Int, String)] = List((1,3,ee), (1,2,ok))
You can use Ordering:
scala> SortedSet(l: _*)(Ordering[(Int, Int)].on(x => (x._1, x._2))).toList
res33: List[(Int, Int, String)] = List((1,2,hello), (1,3,hello), (2,3,world))
The only problem is that the last found element is preserved. For the first one you need to reverse the list:
scala> SortedSet(l.reverse: _*)(Ordering[(Int, Int)].on(x => (x._1, x._2))).toList
res34: List[(Int, Int, String)] = List((1,2,hi), (1,3,hello), (2,3,world))
The reverse is not optimal but maybe it is possible to create the list directly in reversed order, which would avoid the construction of an unnecessary intermediate list.

How to generate the power set of a set in Scala

I have a Set of items of some type and want to generate its power set.
I searched the web and couldn't find any Scala code that adresses this specific task.
This is what I came up with. It allows you to restrict the cardinality of the sets produced by the length parameter.
def power[T](set: Set[T], length: Int) = {
var res = Set[Set[T]]()
res ++= set.map(Set(_))
for (i <- 1 until length)
res = res.map(x => set.map(x + _)).flatten
res
}
This will not include the empty set. To accomplish this you would have to change the last line of the method simply to res + Set()
Any suggestions how this can be accomplished in a more functional style?
Looks like no-one knew about it back in July, but there's a built-in method: subsets.
scala> Set(1,2,3).subsets foreach println
Set()
Set(1)
Set(2)
Set(3)
Set(1, 2)
Set(1, 3)
Set(2, 3)
Set(1, 2, 3)
Notice that if you have a set S and another set T where T = S ∪ {x} (i.e. T is S with one element added) then the powerset of T - P(T) - can be expressed in terms of P(S) and x as follows:
P(T) = P(S) ∪ { p ∪ {x} | p ∈ P(S) }
That is, you can define the powerset recursively (notice how this gives you the size of the powerset for free - i.e. adding 1-element doubles the size of the powerset). So, you can do this tail-recursively in scala as follows:
scala> def power[A](t: Set[A]): Set[Set[A]] = {
| #annotation.tailrec
| def pwr(t: Set[A], ps: Set[Set[A]]): Set[Set[A]] =
| if (t.isEmpty) ps
| else pwr(t.tail, ps ++ (ps map (_ + t.head)))
|
| pwr(t, Set(Set.empty[A])) //Powerset of ∅ is {∅}
| }
power: [A](t: Set[A])Set[Set[A]]
Then:
scala> power(Set(1, 2, 3))
res2: Set[Set[Int]] = Set(Set(1, 2, 3), Set(2, 3), Set(), Set(3), Set(2), Set(1), Set(1, 3), Set(1, 2))
It actually looks much nicer doing the same with a List (i.e. a recursive ADT):
scala> def power[A](s: List[A]): List[List[A]] = {
| #annotation.tailrec
| def pwr(s: List[A], acc: List[List[A]]): List[List[A]] = s match {
| case Nil => acc
| case a :: as => pwr(as, acc ::: (acc map (a :: _)))
| }
| pwr(s, Nil :: Nil)
| }
power: [A](s: List[A])List[List[A]]
Here's one of the more interesting ways to write it:
import scalaz._, Scalaz._
def powerSet[A](xs: List[A]) = xs filterM (_ => true :: false :: Nil)
Which works as expected:
scala> powerSet(List(1, 2, 3)) foreach println
List(1, 2, 3)
List(1, 2)
List(1, 3)
List(1)
List(2, 3)
List(2)
List(3)
List()
See for example this discussion thread for an explanation of how it works.
(And as debilski notes in the comments, ListW also pimps powerset onto List, but that's no fun.)
Use the built-in combinations function:
val xs = Seq(1,2,3)
(0 to xs.size) flatMap xs.combinations
// Vector(List(), List(1), List(2), List(3), List(1, 2), List(1, 3), List(2, 3),
// List(1, 2, 3))
Note, I cheated and used a Seq, because for reasons unknown, combinations is defined on SeqLike. So with a set, you need to convert to/from a Seq:
val xs = Set(1,2,3)
(0 to xs.size).flatMap(xs.toSeq.combinations).map(_.toSet).toSet
//Set(Set(1, 2, 3), Set(2, 3), Set(), Set(3), Set(2), Set(1), Set(1, 3),
//Set(1, 2))
Can be as simple as:
def powerSet[A](xs: Seq[A]): Seq[Seq[A]] =
xs.foldLeft(Seq(Seq[A]())) {(sets, set) => sets ++ sets.map(_ :+ set)}
Recursive implementation:
def powerSet[A](xs: Seq[A]): Seq[Seq[A]] = {
def go(xsRemaining: Seq[A], sets: Seq[Seq[A]]): Seq[Seq[A]] = xsRemaining match {
case Nil => sets
case y :: ys => go(ys, sets ++ sets.map(_ :+ y))
}
go(xs, Seq[Seq[A]](Seq[A]()))
}
All the other answers seemed a bit complicated, here is a simple function:
def powerSet (l:List[_]) : List[List[Any]] =
l match {
case Nil => List(List())
case x::xs =>
var a = powerSet(xs)
a.map(n => n:::List(x)):::a
}
so
powerSet(List('a','b','c'))
will produce the following result
res0: List[List[Any]] = List(List(c, b, a), List(b, a), List(c, a), List(a), List(c, b), List(b), List(c), List())
Here's another (lazy) version... since we're collecting ways of computing the power set, I thought I'd add it:
def powerset[A](s: Seq[A]) =
Iterator.range(0, 1 << s.length).map(i =>
Iterator.range(0, s.length).withFilter(j =>
(i >> j) % 2 == 1
).map(s)
)
Here's a simple, recursive solution using a helper function:
def concatElemToList[A](a: A, list: List[A]): List[Any] = (a,list) match {
case (x, Nil) => List(List(x))
case (x, ((h:List[_]) :: t)) => (x :: h) :: concatElemToList(x, t)
case (x, (h::t)) => List(x, h) :: concatElemToList(x, t)
}
def powerSetRec[A] (a: List[A]): List[Any] = a match {
case Nil => List()
case (h::t) => powerSetRec(t) ++ concatElemToList(h, powerSetRec (t))
}
so the call of
powerSetRec(List("a", "b", "c"))
will give the result
List(List(c), List(b, c), List(b), List(a, c), List(a, b, c), List(a, b), List(a))