El MapLike
rasgo de Scala tiene un método
mapValues [C] (f: (B) ⇒ C): Map[A, C]
Pero a veces quiero un tipo diferente:
mapKeysAndValues [C] (f: (A, B) ⇒ C): Map[A, C]
¿Hay una forma sencilla de hacer esto que me falta? Por supuesto, esto se puede hacer con un pliegue.
f : (A,B) => (A,C)
, simplemente puede hacerlom.map(f.tupled)
. Funciona con,val f = (x: String, y: Int) => (x, y+1)
pero extrañamente la respuesta se queja si defino de maneraf
equivalentedef
.case
aquí?{case (key, value) => ...}
es solo una coincidencia de patrones en este caso. En lugar de proporcionar una función a amap
, le doy una función parcial.case
le permitirá poner tipos en su patrón, pero esto no es seguro ya que podría crear un error en tiempo de ejecución (porque es solo una coincidencia de patrón). Mientras tanto, si alguna vez cambia la estructura de la colección debajo de lamap
función de modo que haya muy pocos o demasiados objetos para interpretar(key, value)
, una vez más, espero que obtenga un error de tiempo de ejecución. :(¿Qué pasa con este código:
val m = Map(1 -> "one", 2 -> "two") def f(k: Int, v: String) = k + "-" + v m map {case (k, v) => (k, f(k, v))}
Que produce:
Map(1 -> 1-one, 2 -> 2-two)
Esto se puede empaquetar en el método de utilidad:
def mapKeysAndValues[A,B,C](input: Map[A,B], fun: (A, B) => C) = input map {case(k,v) => (k, fun(k, v))}
Uso:
mapKeysAndValues( Map(1 -> "one", 2 -> "two"), (k: Int, v: String) => k + "-" + v )
fuente
MapLike#transform
?m map (t => (t._1, t._2 + 1)) m map (t => t._1 -> t._2 + 1)
fuente
Con algo de Scalaz:
scala> def fst[A, B] = (x: (A, B)) => x._1 fst: [A, B]=> (A, B) => A scala> Map(1 -> "Lorem", 2 -> "Ipsum").map(fst &&& Function.tupled(_.toString + _)) res1: scala.collection.immutable.Map[Int,java.lang.String] = Map(1 -> 1Lorem, 2 -> 2Ipsum)
Me gusta más la solución de @ tenshi.
fuente
Podría crear una clase de utilidad:
class MyMapLike[K,V](m:MapLike[K,V,_]){ def mapKeysAndValues[R](f: (K, V) => R)={ m.map{case (k,v)=> f(k,v)} } } object MyMapLike{ implicit def maplike2mymaplike[K,V](ml:MapLike[K,V,_]):MyMapLike[K,V]=new MyMapLike(m) } import MyMapLike._ Map(1 -> "one", 2 -> "two").mapKeysAndValues(k,v=>v*k)
Código no probado, pero debería funcionar de alguna manera similar.
fuente