英文:
How to take all keys and values of a map and pass as args to a function in golang?
问题
我遇到了这样的情况:
首先得到了一个地图,它的大小是未知的。
例如:myMap map[string]string
然后,我想将地图的所有键和值作为函数的参数
例如 func(key1, key2, ..., value1, value2, ...)
。
一个示例函数:https://godoc.org/github.com/garyburd/redigo/redis#Script.Do
如何在Go语言中实现这个功能?
尽可能高效。
非常感谢您的帮助
英文:
I encountered such a situation:
Got a map first, and its size is unknown.
E.g.: myMap map[string]string
And then, I would take all the keys and values of the map as a function's args
e.g func(key1, key2, ..., value1, value2, ...)
An example func: https://godoc.org/github.com/garyburd/redigo/redis#Script.Do
How to achieve this in go?
As efficient as impossible.
Any help will be appreciated
答案1
得分: 5
我们可以使用内置的len()
函数查询地图的长度。因此,我们可以创建一个足够大的切片来容纳所有的键和所有的值。
之后,只需要对地图进行一次迭代,就可以将切片的前一半填充为键,后一半填充为值。
这是效率最高的方法:不调用内置的append()
函数,只对地图进行一次迭代。
让我们看一个接收键和值的示例函数。这个函数只是打印它们:
func pairs(keysvalues ...string) {
for _, s := range keysvalues {
fmt.Print(s, ", ")
}
}
以及创建keysvalues
切片的代码:
m := map[string]string{
"a": "A",
"b": "B",
"c": "C",
}
count := len(m)
all := make([]string, count*2)
i := 0
for k, v := range m {
all[i], all[count+i] = k, v
i++
}
一旦你有了all
切片,你可以这样调用pairs()
函数:
pairs(all...)
请注意,地图的迭代顺序是不确定的,它可能在每次迭代时发生变化。
示例输出(在Go Playground上尝试):
a, b, c, A, B, C,
注意:
在你的问题中,你指示所有的键先出现,然后是所有的值:
func(key1, key2, ..., value1, value2, ...)
实际上,这种情况很少见,通常会列出键值对。使用键值对的变体更容易处理:
func pairs(key1, value1, key2, value2, ... keyn, valuen)
如果我们想要生成这种键值对列表,非常类似的代码如下:
count := len(m)
all := make([]string, count*2)
i := 0
for k, v := range m {
all[i], all[i+1] = k, v
i += 2
}
英文:
We can query the length of the map with the builtin len()
function. So we can create a big-enough slice to hold all the keys and all the values.
After that it's enough to iterate over the map only once, and you can fill the first half of the slice with the keys, and the second half of the slice with the values.
This is as efficient as it can get: no builtin append()
is called, and we iterate over the map only once.
Let's see an example function that will receive the keys and values. This one just prints all of them:
func pairs(keysvalues ...string) {
for _, s := range keysvalues {
fmt.Print(s, ", ")
}
}
And the code that creates the keysvalues
slice:
m := map[string]string{
"a": "A",
"b": "B",
"c": "C",
}
count := len(m)
all := make([]string, count*2)
i := 0
for k, v := range m {
all[i], all[count+i] = k, v
i++
}
Once you have the all
slice, you can call the pairs()
function like this:
pairs(all...)
Note though that the iteration order over a map is not deterministic, it may change from iteration to iteration.
Example output (try it on the Go Playground):
a, b, c, A, B, C,
Note:
In your question you indicated that all keys come first and then follow all the values:
> func(key1, key2, ..., value1, value2, ...)
In practice this is rare and often the key-value pairs are listed. It's much easier to work/process this variant:
func pairs(key1, value1, key2, value2, ... keyn, valuen)
If we would want to produce this key-value pair list, very similarly it would look like this:
count := len(m)
all := make([]string, count*2)
i := 0
for k, v := range m {
all[i], all[i+1] = k, v
i += 2
}
答案2
得分: 2
例如,
package main
import "fmt"
func fn(args ...string) { fmt.Println(args) }
func main() {
m := map[string]string{"k1": "v1", "k2": "v2"}
args := make([]string, 0, 2*len(m))
for key, value := range m {
args = append(args, key)
args = append(args, value)
}
fmt.Println(args)
fn(args...)
}
输出:
[k1 v1 k2 v2]
[k1 v1 k2 v2]
英文:
For example,
package main
import "fmt"
func fn(args ...string) { fmt.Println(args) }
func main() {
m := map[string]string{"k1": "v1", "k2": "v2"}
args := make([]string, 0, 2*len(m))
for key, value := range m {
args = append(args, key)
args = append(args, value)
}
fmt.Println(args)
fn(args...)
}
Output:
[k1 v1 k2 v2]
[k1 v1 k2 v2]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论