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.

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)}

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
)

Bukankah ini sama dengan MapLike#transform?
Hosam Aly


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.


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.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.