MapLikeCecha Scali ma metodę
mapValues [C] (f: (B) ⇒ C): Map[A, C]
Ale czasami chcę innego typu:
mapKeysAndValues [C] (f: (A, B) ⇒ C): Map[A, C]
Czy jest na to prosty sposób, którego mi brakuje? Oczywiście można to zrobić za pomocą fałdy.
MapLikeCecha Scali ma metodę
mapValues [C] (f: (B) ⇒ C): Map[A, C]
Ale czasami chcę innego typu:
mapKeysAndValues [C] (f: (A, B) ⇒ C): Map[A, C]
Czy jest na to prosty sposób, którego mi brakuje? Oczywiście można to zrobić za pomocą fałdy.
Odpowiedzi:
mapmetoda iteruje przez wszystkie (key, value)pary. Możesz go używać w ten sposób:
val m = Map("a" -> 1, "b" -> 2)
val incM = m map {case (key, value) => (key, value + 1)}
case?
{case (key, value) => ...}to w tym przypadku tylko dopasowanie do wzorca. Zamiast mapnadawać funkcję a , daję mu funkcję częściową.
casepozwoli ci umieścić typy w swoim wzorcu, ale nie jest to bezpieczne, ponieważ może spowodować błąd w czasie wykonywania (ponieważ jest to tylko dopasowanie do wzorca). W międzyczasie, jeśli kiedykolwiek zmienisz strukturę kolekcji pod mapfunkcją, tak że jest zbyt mało lub zbyt wiele obiektów do zinterpretowania jako (key, value), po raz kolejny spodziewam się, że wystąpi błąd wykonania. :(
A co z tym kodem:
val m = Map(1 -> "one", 2 -> "two")
def f(k: Int, v: String) = k + "-" + v
m map {case (k, v) => (k, f(k, v))}
Który produkuje:
Map(1 -> 1-one, 2 -> 2-two)
Można to spakować do metody narzędziowej:
def mapKeysAndValues[A,B,C](input: Map[A,B], fun: (A, B) => C) =
input map {case(k,v) => (k, fun(k, v))}
Stosowanie:
mapKeysAndValues(
Map(1 -> "one", 2 -> "two"),
(k: Int, v: String) => k + "-" + v
)
MapLike#transform?
m map (t => (t._1, t._2 + 1))
m map (t => t._1 -> t._2 + 1)
Z niektórymi 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)
Bardziej podoba mi się rozwiązanie @ tenshi.
Możesz stworzyć klasę użytkową:
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)
Kod nie jest testowany, ale powinien działać podobnie.
f : (A,B) => (A,C), możesz po prostum.map(f.tupled). Działa z,val f = (x: String, y: Int) => (x, y+1)ale dziwnie odpowiedź narzeka, jeśli zdefiniujęfrównoważnie zdef.