एक स्काला मैप की कुंजी और मान दोनों को मैप करें


89

स्काला की MapLikeविशेषता में एक विधि है

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

लेकिन मैं कभी-कभी एक अलग प्रकार चाहता हूं:

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

क्या ऐसा करने का एक सरल तरीका है जो मुझे याद आ रहा है? बेशक, यह एक गुना के साथ किया जा सकता है।

जवाबों:


166

mapविधि पुनरावृति हालांकि सभी (key, value)जोड़े। आप इसे इस तरह से उपयोग कर सकते हैं:

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

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

8
यदि आपके पास पहले से ही कोई फ़ंक्शन है f : (A,B) => (A,C), तो आप बस कर सकते हैं m.map(f.tupled)। के साथ काम करता है, val f = (x: String, y: Int) => (x, y+1)लेकिन अजीब तरह से जवाब शिकायत करता है अगर मैं fबराबर के साथ परिभाषित करता हूं def
डैन बर्टन

2
caseयहाँ कीवर्ड क्या प्राप्त करता है?
सर्वव्यापी

@Omnipresent {case (key, value) => ...}इस मामले में केवल एक पैटर्न-मिलान है। एक समारोह प्रदान करने के बजाय map, मैं इसे आंशिक कार्य दे रहा हूं।
दसवीं सिप

नोट: caseआपको इसके पैटर्न में टाइप करने देगा, लेकिन यह सुरक्षित नहीं है क्योंकि यह रनटाइम त्रुटि पैदा कर सकता है (क्योंकि यह सिर्फ एक पैटर्न मैच है)। इस बीच, यदि आप कभी भी mapफ़ंक्शन के नीचे संग्रह की संरचना को बदलते हैं ताकि व्याख्या करने के लिए बहुत कम या बहुत अधिक ऑब्जेक्ट हों (key, value), तो एक बार फिर, मुझे उम्मीद है कि आपको एक रनटाइम त्रुटि मिलेगी। :(
combinatorist

8

इस कोड के बारे में क्या:

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?
होसम ऐली


2

कुछ शिलाज़ के साथ:

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)

मुझे @ दहाई का समाधान बेहतर लगता है।


0

आप एक उपयोगिता वर्ग बना सकते हैं:

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)

कोड का परीक्षण नहीं किया गया, लेकिन इसे किसी तरह सिमरिलर की तरह काम करना चाहिए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.