मैं अपरिवर्तनीय को कैसे परिवर्तित कर सकता हूं।


93

मैं कैसे परिवर्तित कर सकते हैं immutable.Mapकरने के लिए mutable.Mapस्काला में तो मैं में मान अद्यतन कर सकते हैं Map?

जवाबों:


126

सबसे साफ तरीका यह होगा कि mutable.Mapवेरगेज कारखाने का उपयोग किया जाए । ++दृष्टिकोण के विपरीत , यह CanBuildFromतंत्र का उपयोग करता है, और इसलिए अधिक कुशल होने की क्षमता है यदि पुस्तकालय कोड इसका लाभ उठाने के लिए लिखा गया था:

val m = collection.immutable.Map(1->"one",2->"Two")
val n = collection.mutable.Map(m.toSeq: _*) 

यह काम करता है क्योंकि Mapजोड़े के अनुक्रम के रूप में भी देखा जा सकता है।


2
क्या आप समझा सकते हैं, पैरामीटर पास करते समय आप दूसरी पंक्ति में किस वाक्यविन्यास का उपयोग करते हैं? कोलन क्या करता है?
हेनजी

7
: _*टाइप अस्क्रिप्शन की तरह है, कंपाइलर को यह बताना कि किसी दिए गए एक्सप्रेशन को किस टाइप का असाइन करना है। आप इसे यहाँ कह सकते हैं कि "इस अनुक्रम को लें, और इसे कई प्रकार के वैराग परमों के रूप में माना जाता है।"
केविन राइट

16
संग्रह पुस्तकालयों के साथ कुछ गलत है अगर यह सबसे साफ है;)
20

2
@matt को अलियास आयात के साथ थोड़ा कम किया जा सकता है, लेकिन ध्यान रखें कि स्केला के लिए अपरिवर्तनीयता का त्याग करना बहुत ही गैर-मुहावरेदार है, न कि जिस तरह की चीज मैं इसे और भी आसान बनाकर हतोत्साहित करूंगा। जिज्ञासा से बाहर ... , और कैसे आप इसे और अधिक सफाई से करने का प्रस्ताव कर सकते हैं, यदि प्रतिलिपि के माध्यम से नहीं?
केविन राइट

यह मेरी बात है, मैं नहीं कर सकता, लेकिन एक बेहतर संग्रह पुस्तकालय यह संभव बना सकता है, IMHO।
मैटानस्टर mat

41
val myImmutableMap = collection.immutable.Map(1->"one",2->"two")
val myMutableMap = collection.mutable.Map() ++ myImmutableMap

1
क्या आप जानते हैं कि इस समय की विषमता की जटिलता है? मुझे पता है कि क्लोजर अपने किसी भी लगातार संग्रह को "क्षणिक" एक में बदल सकता है (यानी एक लीनियर-टाइप किए गए म्यूटेशन फ़ंक्शंस के साथ) और O(1)चरणों में लगातार एक में । यह प्रतीत होता है O(n), हालांकि यह इस बात पर निर्भर करता है कि कार्यान्वयन कितना चतुर ++है।
Jörg W Mittag

1
@ Jörg - मुझे पूरा यकीन है कि यह एक है O(n)। सीमा में जैसा कि आप सब कुछ बदलते हैं, यह होना चाहिए O(n), हालांकि आप समय बचाने के लिए नई कॉपी के निर्माण को स्थगित करने का प्रयास कर सकते हैं, या आप मूल नक्शे के बजाय परिवर्तनशील पठन द्वारा अपनी पहुंच समय को दोगुना कर सकते हैं। कौन सा सबसे अच्छा प्रदर्शन करता है शायद आपके उपयोग के मामले पर निर्भर करता है।
रेक्स केर

1
@ रुस्तम - मानचित्र अनियंत्रित हैं। वे (जैसे हैश मैप के साथ) जैसा भी महसूस करें, वे क्रम में दिखाई देंगे। विशेष रूप से, अपरिवर्तनीय मानचित्रों में वास्तव में छोटे मानचित्रों के लिए विशेष मामले होते हैं जो कि उत्परिवर्तित मानचित्रों से भिन्न होते हैं।
रेक्स केर

@ रुस्तम मानचित्र का आदेश नहीं दिया गया है।
डैनियल सी। सोबरल

4

कैसे के बारे में collection.breakOut का उपयोग कर?

import collection.{mutable, immutable, breakOut}
val myImmutableMap = immutable.Map(1->"one",2->"two")
val myMutableMap: mutable.Map[Int, String] = myImmutableMap.map(identity)(breakOut)

यह है शांत, लेकिन जैसा कि मूल रूप से एक ही बात करता है mutable.Map#applyसाथ में थोड़ा और अधिक बॉयलरप्लेट।
केविन राइट


1

एक खाली उत्परिवर्ती बनाने का एक प्रकार है Mapजिसमें अपरिवर्तनीय से लिया गया डिफ़ॉल्ट मान है Map। आप किसी भी समय मान जमा कर सकते हैं और डिफ़ॉल्ट को ओवरराइड कर सकते हैं:

scala> import collection.immutable.{Map => IMap}
//import collection.immutable.{Map=>IMap}

scala> import collection.mutable.HashMap
//import collection.mutable.HashMap

scala> val iMap = IMap(1 -> "one", 2 -> "two")
//iMap: scala.collection.immutable.Map[Int,java.lang.String] = Map((1,one), (2,two))

scala> val mMap = new HashMap[Int,String] {      
     | override def default(key: Int): String = iMap(key)
     | }
//mMap: scala.collection.mutable.HashMap[Int,String] = Map()

scala> mMap(1)
//res0: String = one

scala> mMap(2)
//res1: String = two

scala> mMap(3)
//java.util.NoSuchElementException: key not found: 3
//  at scala.collection.MapLike$class.default(MapLike.scala:223)
//  at scala.collection.immutable.Map$Map2.default(Map.scala:110)
//  at scala.collection.MapLike$class.apply(MapLike.scala:134)
//  at scala.collection.immutable.Map$Map2.apply(Map.scala:110)
//  at $anon$1.default(<console>:9)
//  at $anon$1.default(<console>:8)
//  at scala.collection.MapLike$class.apply(MapLike.scala:134)....

scala> mMap(2) = "three"

scala> mMap(2)          
//res4: String = three

कैविएट (रेक्स केर द्वारा टिप्पणी देखें): आप अपरिवर्तनीय नक्शे से आने वाले तत्वों को हटाने में सक्षम नहीं होंगे:

scala> mMap.remove(1)
//res5: Option[String] = None

scala> mMap(1)
//res6: String = one

3
यह कुछ मामलों में उपयोगी है, लेकिन ध्यान दें कि आप अपने नए नक्शे में एक तत्व को हटाने में असमर्थ हैं जो आपके डिफ़ॉल्ट नक्शे में मौजूद था; आप केवल डिफॉल्ट को कवर और उजागर कर सकते हैं।
रेक्स केर

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