У Scala MapLike
есть метод
mapValues [C] (f: (B) ⇒ C): Map[A, C]
Но иногда хочется другого типа:
mapKeysAndValues [C] (f: (A, B) ⇒ C): Map[A, C]
Есть ли простой способ сделать это, которого мне не хватает? Конечно, это можно сделать со складкой.
f : (A,B) => (A,C)
, то можете простоm.map(f.tupled)
. Работает с,val f = (x: String, y: Int) => (x, y+1)
но, как ни странно, ответ жалуется, если я определяюf
эквивалентно сdef
.case
?{case (key, value) => ...}
в этом случае - это просто сопоставление с образцом. Вместо того, чтобы предоставлять функцию amap
, я передаю ему частичную функцию.case
позволит вам помещать типы в его шаблон, но это небезопасно, так как может вызвать ошибку времени выполнения (потому что это просто совпадение с шаблоном). Между тем, если вы когда-нибудь измените структуру коллекции подmap
функцией так, что будет слишком мало или слишком много объектов для интерпретации(key, value)
, то опять же, я ожидаю, что вы получите ошибку времени выполнения. :(А как насчет этого кода:
val m = Map(1 -> "one", 2 -> "two") def f(k: Int, v: String) = k + "-" + v m map {case (k, v) => (k, f(k, v))}
Что производит:
Map(1 -> 1-one, 2 -> 2-two)
Это можно упаковать в служебный метод:
def mapKeysAndValues[A,B,C](input: Map[A,B], fun: (A, B) => C) = input map {case(k,v) => (k, fun(k, v))}
Применение:
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)
источник
С некоторым Скалазом:
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)
Мне больше нравится решение @tenshi.
источник
Вы можете создать служебный класс:
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)
Код не тестировался, но он должен работать примерно так же.
источник