Memetakan kedua kunci dan nilai Peta Scala

89

Ciri Scala MapLikememiliki metode

mapValues [C] (f: (B) ⇒ C): Map[A, C] 

Tapi terkadang saya menginginkan tipe yang berbeda:

mapKeysAndValues [C] (f: (A, B) ⇒ C): Map[A, C] 

Apakah ada cara sederhana untuk melakukan ini yang saya lewatkan? Tentu saja, ini bisa dilakukan dengan lipatan.

Alexey Romanov
sumber

Jawaban:

166

mapmetode iterasi meskipun semua (key, value)pasangan. Anda bisa menggunakannya seperti ini:

val m = Map("a" -> 1, "b" -> 2)

val incM = m map {case (key, value) => (key, value + 1)}
tenshi
sumber
8
Jika Anda sudah memiliki sebuah fungsi f : (A,B) => (A,C), maka Anda bisa m.map(f.tupled). Bekerja dengan val f = (x: String, y: Int) => (x, y+1)tetapi anehnya repl mengeluh jika saya mendefinisikan fdengan ekuivalen def.
Dan Burton
2
apa yang casedicapai kata kunci di sini?
Hadir di mana-mana
@Omnipresent {case (key, value) => ...}hanyalah pencocokan pola dalam kasus ini. Alih-alih memberikan fungsi ke a map, saya memberikannya fungsi parsial.
tenshi
Catatan: caseakan membiarkan Anda memasukkan tipe ke dalam polanya, tetapi ini tidak aman karena dapat membuat kesalahan waktu proses (karena ini hanya kecocokan pola). Sementara itu, jika Anda pernah mengubah struktur koleksi di bawah mapfungsi sehingga ada terlalu sedikit atau terlalu banyak objek untuk diinterpretasikan (key, value), maka sekali lagi, saya berharap Anda akan mendapatkan error runtime. :(
kombinatorist
8

Bagaimana dengan kode ini:

val m = Map(1 -> "one", 2 -> "two")
def f(k: Int, v: String) = k + "-" + v
m map {case (k, v) => (k, f(k, v))}

Yang menghasilkan:

 Map(1 -> 1-one, 2 -> 2-two)

Ini dapat dikemas ke dalam metode utilitas:

def mapKeysAndValues[A,B,C](input: Map[A,B], fun: (A, B) => C) = 
  input map {case(k,v) => (k, fun(k, v))}

Pemakaian:

mapKeysAndValues(
  Map(1 -> "one", 2 -> "two"), 
  (k: Int, v: String) => k + "-" + v
)
Tomasz Nurkiewicz
sumber
Bukankah ini sama dengan MapLike#transform?
Hosam Aly
5
m map (t => (t._1, t._2 + 1))

m map (t => t._1 -> t._2 + 1)
Grigory Kislin
sumber
2

Dengan beberapa 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)

Saya lebih suka solusi @ tenshi.

missingfaktor
sumber
0

Anda dapat membuat kelas utilitas:

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)

Kode tidak diuji tetapi harus bekerja sama seperti itu.

Alex
sumber