0

Given the following code :

def map1[A,B,C](s: Seq[(A, B)])(f: A => C) : Seq[(C, B)] = 
  s.map { case (a, b) => (f(a), b) }

Is there a better way to code that (maybe something exist in scalaz) ?

Can you help me to find a better name ?

Is there a more generic abstraction to use (Iterable, TraversableOnce) ?

Yann Moisan
  • 8,161
  • 8
  • 47
  • 91
  • Is this definitely the code that you want? Right now it looks like you're only applying the function to the first element of the tuple – Falmarri Mar 07 '15 at 00:07
  • 1
    Why did you re-post this not even an hour later? http://stackoverflow.com/questions/28908457/flatmap-on-a-sequence-of-tuples – Michael Zajac Mar 07 '15 at 01:17
  • Not the same ! It's a map on keys, and the other question is a flatMap on values. – Yann Moisan Mar 07 '15 at 09:50

2 Answers2

3

You could define an extension method:

import scala.collection.GenTraversable
import scala.collection.GenTraversableLike
import scala.collection.generic.CanBuildFrom

implicit class WithMapKeys[A, B, Repr](val self: GenTraversableLike[(A, B), Repr]) extends AnyVal {
  def mapKeys[C, That](f: A => C)(implicit bf: CanBuildFrom[Repr, (C, B), That]) = {
    self.map(x => f(x._1) -> x._2)
  }
}

Then:

Vector(1->"a", 2->"b").mapKeys(_+2)
// res0: scala.collection.immutable.Vector[(Int, String)] = Vector((3,a), (4,b))

Map(1->"a", 2->"b").mapKeys(_+2)
// res1: scala.collection.immutable.Map[Int,String] = Map(3 -> a, 4 -> b)

Similarly for Iterator:

implicit class WithMapKeysItr[A, B](val self: Iterator[(A, B)]) extends AnyVal {
  def mapKeys[C](f: A => C): Iterator[(C, B)] = {
    self.map(x => f(x._1) -> x._2)
  }
}

val i2 = Iterator(1->"a", 2->"b").mapKeys(_+2)
// i2: Iterator[(Int, String)] = non-empty iterator
i2.toVector
// res2: Vector[(Int, String)] = Vector((3,a), (4,b))

val to: TraversableOnce[(Int, String)] = Vector(1->"a", 2->"b")
val i3 = to.toIterator.mapKeys(_+2)
// i3: Iterator[(Int, String)] = non-empty iterator
i3.toMap
// res3: scala.collection.immutable.Map[Int,String] = Map(3 -> a, 4 -> b)
dhg
  • 52,383
  • 8
  • 123
  • 144
  • Why using GenTraversable, GenTraversableLike and not just Traversable ? – Yann Moisan Mar 07 '15 at 12:04
  • GenTraversable is broader. It includes Traversable, but also parallel collections. Scala's built-in `Seq.flatMap`, for example, takes GenTraversableOnce. – dhg Mar 07 '15 at 18:03
1

Shapeless could make it a little more prettier (without pattern matching):

import shapeless.syntax.std.tuple._
def mapKeys[A,B,C](s: Seq[(A, B)])(f: A => C) : Seq[(C, B)] = 
   s.map(x => x.updatedAt(0, f(x.head)))
dk14
  • 22,206
  • 4
  • 51
  • 88