2011-09-15 9 views
59

को देखते हुए में कोई नक्शा के सभी तत्वों को कॉपी कर रहा हैएक और

var dst, src map[K]V 

मैं

for k, v := range src { 
    dst[k] = v 
} 

करके dst में src से सभी प्रविष्टियों कॉपी कर सकते हैं वहाँ यह करने के लिए एक और अधिक मुहावरेदार रास्ता नहीं है?

copy केवल स्लाइस पर काम करता है (और string स्रोत के रूप में)।

उत्तर

44

यह मेरे लिए ऐसा करने का एक बिल्कुल सही तरीका है। मुझे नहीं लगता कि एक मानचित्र को दूसरे में कॉपी करना एक-लाइनर समाधान के लिए पर्याप्त है।

+24

इस्तेमाल कर सकते हैं यह एक शर्म की बात है 'copy' केवल स्लाइस पर काम करता है। –

+16

"मुझे नहीं लगता कि एक मानचित्र को दूसरे में कॉपी करना काफी आम है" ... यह मेरा मुख्य पालतू शिखर है। यह देशी भाषाओं पर हर दूसरी भाषा पर वास्तव में करना आसान है। –

+7

@EduFelipe मैं सहमत हूं। गो के अंतर्निहित जेनेरिक प्रकारों (जैसे मानचित्र) की विशेष प्रकृति, और उपयोगकर्ता द्वारा परिभाषित प्रकारों (जैसे जेनेरिक के लिए कोई समर्थन नहीं) में समान कार्यक्षमता प्राप्त करने के किसी भी तरीके की कमी, गो के साथ मेरे सबसे बड़े मुद्दों में से एक है। और यह सिर्फ कई कारणों में से एक है कि मुझे जंग पसंद क्यों है। –

7

एक साधारण for range पाश का उपयोग करना सबसे कुशल समाधान है।

ध्यान दें कि एक निर्मित copy की स्मृति को dst के पते पर कॉपी नहीं कर सका क्योंकि उनके पास पूरी तरह से अलग मेमोरी लेआउट हो सकता है। मानचित्र उन में संग्रहीत वस्तुओं की संख्या को समायोजित करने के लिए बढ़ते हैं। तो उदाहरण के लिए यदि आपके पास दस लाख तत्वों वाला नक्शा है, तो यह ताजा नए बनाए गए नए मानचित्र की तुलना में बहुत अधिक स्मृति रखता है, और इसलिए एक निर्मित copy नई आवंटित किए बिना स्मृति की प्रतिलिपि नहीं बना सका।

यदि आपका नक्शा बड़ा है, आप तत्वों को कॉपी करता है, तो आप गंतव्य नक्शा rehashing और पुनः आबंटन से बचने के लिए एक बड़े पर्याप्त क्षमता वाले बना सकते में तेजी लाने के कर सकते हैं (आरंभिक क्षमता इसके आकार के लिए बाध्य नहीं करता है), जैसे:

dst := make(map[K]V, len(src)) 

for k, v := range src { 
    dst[k] = v 
} 

यदि प्रदर्शन एक मुद्दा (जैसे आप छोटे नक्शे के साथ काम कर रहे हैं), एक सामान्य समाधान reflect पैकेज का उपयोग कर बनाया जा सकता है नहीं है:

func MapCopy(dst, src interface{}) { 
    dv, sv := reflect.ValueOf(dst), reflect.ValueOf(src) 

    for _, k := range sv.MapKeys() { 
     dv.SetMapIndex(k, sv.MapIndex(k)) 
    } 
} 

यह समाधान की जाँच नहीं करता है, तो तर्क वास्तव में नक्शे कर रहे हैं और यदि गंतव्य नहीं है nil। यह परीक्षण:

m1 := map[int]string{1: "one", 2: "two"} 
m2 := map[int]string{} 
MapCopy(m2, m1) 
fmt.Println(m2) 

m3 := map[string]int{"one": 1, "two": 2} 
m4 := map[string]int{} 
MapCopy(m4, m3) 
fmt.Println(m4) 

आउटपुट (Go Playground पर यह कोशिश):

map[1:one 2:two] 
map[one:1 two:2] 
2

आप github.com/linkosmos/mapop

input := map[string]interface{}{ 
    "Key1": 2, 
    "key3": nil, 
    "val": 2, 
    "val2": "str", 
    "val3": 4, 
} 

input2 := map[string]interface{}{ 
    "a2": "str", 
    "a3": 4, 
} 

input = mapop.Merge(input, input2) 

input{"Key1": 2, "key3": nil, "val": 2, "val2": "str", "val3": 4, "a2": "str", "a3": 4}