গো-এ কোনও মানচিত্র থেকে কীগুলির টুকরো টুকরো টানানোর সহজ / সুন্দর উপায় আছে?
বর্তমানে আমি মানচিত্রে পুনরাবৃত্তি করছি এবং একটি টুকরোতে কীগুলি অনুলিপি করছি:
i := 0
keys := make([]int, len(mymap))
for k := range mymap {
keys[i] = k
i++
}
গো-এ কোনও মানচিত্র থেকে কীগুলির টুকরো টুকরো টানানোর সহজ / সুন্দর উপায় আছে?
বর্তমানে আমি মানচিত্রে পুনরাবৃত্তি করছি এবং একটি টুকরোতে কীগুলি অনুলিপি করছি:
i := 0
keys := make([]int, len(mymap))
for k := range mymap {
keys[i] = k
i++
}
উত্তর:
উদাহরণ স্বরূপ,
package main
func main() {
mymap := make(map[int]string)
keys := make([]int, 0, len(mymap))
for k := range mymap {
keys = append(keys, k)
}
}
Go এ দক্ষ হওয়ার জন্য, মেমরির বরাদ্দকে হ্রাস করতে গুরুত্বপূর্ণ।
mymap
স্থানীয় পরিবর্তনশীল না হয় (এবং তাই এটি বৃদ্ধি / সংকোচনের সাপেক্ষে) তবে এটিই একমাত্র সঠিক সমাধান - এটি নিশ্চিত করে যে যদি mymap
আরম্ভের keys
এবং for
লুপের মধ্যে পরিবর্তনগুলির আকার হয় তবে কোনও আউট- সীমাবদ্ধ সমস্যা।
এটি একটি পুরানো প্রশ্ন, তবে এখানে আমার দুটি সেন্ট। পিটারএসওর উত্তরটি আরও সংক্ষিপ্ত, তবে সামান্য কম দক্ষ। আপনি ইতিমধ্যে জানেন যে এটি কতটা বড় হতে চলেছে তাই আপনার অ্যাপেন্ড ব্যবহার করার প্রয়োজন নেই:
keys := make([]int, len(mymap))
i := 0
for k := range mymap {
keys[i] = k
i++
}
বেশিরভাগ পরিস্থিতিতে এটি সম্ভবত খুব বেশি পার্থক্য তৈরি করবে না, তবে এটি খুব বেশি কাজ নয় এবং আমার পরীক্ষাগুলিতে (1,000,000 এলোমেলো int64
কী সহ একটি মানচিত্র ব্যবহার করা এবং তারপরে প্রতিটি পদ্ধতির সাথে দশ বার কীগুলির অ্যারে তৈরি করা), এটি প্রায় ছিল অ্যাপেন্ড ব্যবহারের চেয়ে অ্যারের সদস্যদের সরাসরি বরাদ্দ করতে 20% দ্রুত।
যদিও ক্ষমতা নির্ধারণের পুনঃনির্ধারণগুলি সরিয়ে ফেলা হয়, তবুও প্রতিটি সংযোজনে আপনি ক্ষমতা পৌঁছেছেন কিনা তা পরীক্ষা করতে অতিরিক্ত অতিরিক্ত কাজ করতে হবে।
for i, k := range mymap{
,। এইভাবে আপনার আই ++ লাগবে না?
i, k := range mymap
তবে i
কীগুলি k
হবে এবং মানচিত্রের সেই কীগুলির সাথে সম্পর্কিত মান হবে। এটি আপনাকে কীগুলির একটি স্লাইস পপুলেট করতে সহায়তা করবে না।
আপনি প্যাকেজ "প্রতিচ্ছবি" থেকে স্ট্রাক্ট []Value
পদ্ধতি MapKeys
অনুসারে কীগুলির একটি অ্যারেও নিতে পারেন Value
:
package main
import (
"fmt"
"reflect"
)
func main() {
abc := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
keys := reflect.ValueOf(abc).MapKeys()
fmt.Println(keys) // [a b c]
}
[]string
?
এটি করার একটি দুর্দান্ত উপায় হ'ল append
:
keys = []int{}
for k := range mymap {
keys = append(keys, k)
}
তা ছাড়া, আপনার ভাগ্যের বাইরে — গো কোনও খুব ভাবপূর্ণ ভাষা নয়।
keys = make([]int, 0, len(mymap))
বরাদ্দ থেকে মুক্তি পাবে তবে আমি আশা করি এটি আরও ধীর হবে।
অন্যান্য প্রতিক্রিয়াগুলিতে বর্ণিত তিনটি পদ্ধতিতে আমি একটি স্কেচি বেঞ্চমার্ক তৈরি করেছি।
স্পষ্টতই কীগুলি টানার আগে স্লাইসটি প্রাক-বরাদ্দ করা আইএনগের চেয়ে দ্রুত append
, তবে আশ্চর্যের বিষয় হল, reflect.ValueOf(m).MapKeys()
পদ্ধতিটি পরবর্তীকালের তুলনায় উল্লেখযোগ্যভাবে ধীর:
❯ go run scratch.go
populating
filling 100000000 slots
done in 56.630774791s
running prealloc
took: 9.989049786s
running append
took: 18.948676741s
running reflect
took: 25.50070649s
এখানে কোডটি রয়েছে: https://play.golang.org/p/Z8O6a2jyfTH (খেলার মাঠে এটি চালানো দাবি করে যে এটি খুব বেশি সময় নেয়, তাই ভাল, এটি স্থানীয়ভাবে চালান))
keysAppend
ফাংশনে, আপনি keys
অ্যারের সক্ষমতা সেট করতে পারেন make([]uint64, 0, len(m))
, যা আমার জন্য সেই ক্রিয়াকলাপটির পারফরম্যান্সকে মারাত্মকভাবে পরিবর্তন করেছে।
পরিদর্শন https://play.golang.org/p/dx6PTtuBXQW
package main
import (
"fmt"
"sort"
)
func main() {
mapEg := map[string]string{"c":"a","a":"c","b":"b"}
keys := make([]string, 0, len(mapEg))
for k := range mapEg {
keys = append(keys, k)
}
sort.Strings(keys)
fmt.Println(keys)
}