Scala Haritasının hem anahtarlarını hem de değerlerini eşleyin


89

Scala'nın MapLikeözelliğinin bir yöntemi var

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

Ama bazen farklı bir tür istiyorum:

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

Bunu yapmanın kaçırdığım basit bir yolu var mı? Tabii ki, bu bir katlama ile yapılabilir.

Yanıtlar:


167

mapyöntem tüm (key, value)çiftlere rağmen yinelenir . Bunu şu şekilde kullanabilirsiniz:

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

val incM = m map {case (key, value) => (key, value + 1)}

8
Zaten bir işleviniz f : (A,B) => (A,C)varsa, bunu kolayca yapabilirsiniz m.map(f.tupled). Eşit olarak val f = (x: String, y: Int) => (x, y+1)tanımladığımda repl ile çalışır ama garip bir şekilde şikayet eder . fdef
Dan Burton

2
Anahtar kelime caseburada neyi başarır ?
Omnipresent

@Omnipresent {case (key, value) => ...}, bu durumda sadece bir kalıp eşleştirmesidir. A'ya bir fonksiyon sağlamak yerine, mapona kısmi bir fonksiyon veriyorum.
tenshi

Not: casekendi kalıbına türler koymanıza izin verir, ancak bu, bir çalışma zamanı hatası oluşturabileceğinden güvenli değildir (çünkü yalnızca bir kalıp eşleşmesi). Bu arada, mapişlevin altındaki koleksiyonun yapısını, yorumlanamayacak kadar az veya çok fazla nesne olacak şekilde değiştirirseniz (key, value), bir kez daha, bir çalışma zamanı hatası alacağınızı umuyorum. :(
kombinasyoncu

8

Peki ya bu kod:

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

Hangi üretir:

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

Bu, yardımcı program yöntemine paketlenebilir:

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

Kullanım:

mapKeysAndValues(
  Map(1 -> "one", 2 -> "two"), 
  (k: Int, v: String) => k + "-" + v
)

Bu aynı değil MapLike#transformmi?
Hosam Aly


2

Biraz Scalaz ile:

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'nin çözümünü daha çok beğendim.


0

Bir yardımcı program sınıfı oluşturabilirsiniz:

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 test edilmedi, ancak bir şekilde bunun gibi çalışmalıdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.