Reverse a map in <value, key> format in Golang

huangapple go评论90阅读模式
英文:

Reverse a map in <value, key> format in Golang

问题

我有一个程序的映射表,看起来像这样:

fruit_map := map[string]string {
    "apple": "likey",
    "orange": "no likey",
}

我想要将它反转,使其变成以下形式:

{
    "likey": "apple",
    "no likey": "orange",
}

值中没有重复项。此外,我的映射表很小,大约有200个键。我没有找到任何内置的方法来反转这样的映射表。有没有办法快速地做到这一点?我对空间复杂度不太关心,但解决方案需要快速。

谢谢。

英文:

I have a map for my program that looks like following:

fruit_map := map[string]string {
    &quot;apple&quot;: &quot;likey&quot;,
    &quot;orange&quot;: &quot;no likey&quot;,
}

I would like to reverse it so that it reads the following:

{
    &quot;likey&quot;: &quot;apple&quot;,
    &quot;no likey&quot;: &quot;orange&quot;,
}

There are no duplicates in values. Also, my map is small - about 200 keys. I did not find any built-in method to reverse a map like this. Is there any way to do this fast? I am not much bothered about space complexity, but the solution needs to be fast.

Thanks.

答案1

得分: 12

你可以编写一个for循环来遍历原始映射的键值对,并将它们放入一个新的映射中(参见reverseMap函数)。

代码@https://play.golang.org/p/5y1gABTpdb8

package main

import (
	"fmt"
)

func main() {
	fruit_map := map[string]string{
		"apple":  "likey",
		"orange": "no likey",
	}

	reversedMap := reverseMap(fruit_map)
	fmt.Println(reversedMap)
}

func reverseMap(m map[string]string) map[string]string {
	n := make(map[string]string, len(m))
	for k, v := range m {
		n[v] = k
	}
	return n
}

输出:

map[likey:apple no likey:orange]

顺便说一下,用fruit_map这样的命名方式并不符合Go语言的惯例,你真的应该使用驼峰命名法,比如fruitMap

英文:

You may write a for loop to iterate over the key-value pair of original map, and put them in a new map (see function reverseMap)

Code@https://play.golang.org/p/5y1gABTpdb8

package main

import (
	&quot;fmt&quot;
)

func main() {
	fruit_map := map[string]string{
		&quot;apple&quot;:  &quot;likey&quot;,
		&quot;orange&quot;: &quot;no likey&quot;,
	}

	reversedMap := reverseMap(fruit_map)
	fmt.Println(reversedMap)
}

func reverseMap(m map[string]string) map[string]string {
	n := make(map[string]string, len(m))
	for k, v := range m {
		n[v] = k
	}
	return n
}

Output:

map[likey:apple no likey:orange]

BTW, it is not idiomatic to name go variable like fruit_map, you really should use camel-case, like fruitMap.

答案2

得分: 4

其他答案提供了基于直接处理映射的简单解决方案。

另一种解决方案是将双向映射封装为一个独立的实用程序,这样你可以为其编写全面的单元测试,并能够通过简单的 API 来依赖它的正确操作。

这是我的示例实现(不完整,尚未具备必要的单元测试):

package main

import (
	"fmt"
)

func main() {
	biMap := NewBiMap()
	biMap.Put("apple", "likey")
	biMap.Put("orange", "no likey")
	v, _ := biMap.GetByValue("no likey")
	fmt.Println(v)
}

type BiMap struct {
	ab map[string]string
	ba map[string]string
}

func NewBiMap() *BiMap {
	return &BiMap{make(map[string]string), make(map[string]string)}
}

func (m *BiMap) Put(key, value string) *BiMap {
	m.ab[key] = value
	m.ba[value] = key
	return m
}

func (m *BiMap) GetByKey(key string) (value string, exists bool) {
	value, exists = m.ab[key]
	return
}

func (m *BiMap) GetByValue(value string) (key string, exists bool) {
	key, exists = m.ba[value]
	return
}

func (m *BiMap) Len() int {
	return len(m.ab)
}

func (m *BiMap) DeleteKey(key string) *BiMap {
	value, exists := m.ab[key]
	if exists {
		delete(m.ab, key)
		delete(m.ba, value)
	}
	return m
}

func (m *BiMap) DeleteValue(value string) *BiMap {
	key, exists := m.ba[value]
	if exists {
		delete(m.ab, key)
		delete(m.ba, value)
	}
	return m
}
英文:

The other answers offer the simple solution based on handling the map directly.

An alternative solution is to encapsulate a bidirectional map as a self-contained utility, which has the advantage that you could write thorough unit tests for it and then be able to rely on it to operate correctly via a simple API.

Here's my example implementation (which is incomplete and doesn't yet have the necessary unit tests):

package main

import (
&quot;fmt&quot;
)
func main() {
biMap := NewBiMap()
biMap.Put(&quot;apple&quot;, &quot;likey&quot;)
biMap.Put(&quot;orange&quot;, &quot;no likey&quot;)
v, _ := biMap.GetByValue(&quot;no likey&quot;)
fmt.Println(v)
}
type BiMap struct {
ab map[string]string
ba map[string]string
}
func NewBiMap() *BiMap {
return &amp;BiMap{make(map[string]string), make(map[string]string)}
}
func (m *BiMap) Put(key, value string) *BiMap {
m.ab[key] = value
m.ba[value] = key
return m
}
func (m *BiMap) GetByKey(key string) (value string, exists bool) {
value, exists = m.ab[key]
return
}
func (m *BiMap) GetByValue(value string) (key string, exists bool) {
key, exists = m.ba[value]
return
}
func (m *BiMap) Len() int {
return len(m.ab)
}
func (m *BiMap) DeleteKey(key string) *BiMap {
value, exists := m.ab[key]
if exists {
delete(m.ab, key)
delete(m.ba, value)
}
return m
}
func (m *BiMap) DeleteValue(value string) *BiMap {
key, exists := m.ba[value]
if exists {
delete(m.ab, key)
delete(m.ba, value)
}
return m
}

答案3

得分: 0

你是对的,没有内置的方法可以实现这个,但是非常简单:

package main

import "fmt"

func main() {

	fruit_map := map[string]string{
		"apple":  "likey",
		"orange": "no likey",
	}

	//创建一个新的空映射,用于保存反转后的内容。
	reversed_fruit_map := make(map[string]string)

	for k, v := range fruit_map {
		reversed_fruit_map[v] = k
	}

	fmt.Println(reversed_fruit_map)
}

这将输出以下内容:

map[likey:apple no likey:orange]

playground上查看。如果这是常见的操作,你可以将其提取到自己的函数中。

英文:

You are right, there is nothing built-in to accomplish this but it is really straightforward:

package main
import &quot;fmt&quot;
func main() {
fruit_map := map[string]string{
&quot;apple&quot;:  &quot;likey&quot;,
&quot;orange&quot;: &quot;no likey&quot;,
}
//create your new empty map that will hold your reversed contents.
reversed_fruit_map := make(map[string]string)
for k, v := range fruit_map{
reversed_fruit_map[v] = k
}
fmt.Println(reversed_fruit_map)
}

This outputs the following:

map[likey:apple no likey:orange]

Check it out on the playground. If this is common you can always extract out into your own function.

答案4

得分: 0

没有内置的函数可以做到这一点,但使用for循环非常简单。

fruit_map := map[string]string {
    "apple": "likey",
    "orange": "no likey",
}

reversed_map := make(map[string]string)

for key,value := range fruit_map {
    reversed_map[value] = key
}

参考:http://play.golang.org/p/BQjqUsf9aU

英文:

There isn't a built in function to do that, but it's simple enough with a for loop.

fruit_map := map[string]string {
&quot;apple&quot;: &quot;likey&quot;,
&quot;orange&quot;: &quot;no likey&quot;,
}
reversed_map := make(map[string]string)
for key,value := range fruit_map {
reversed_map[value] = key
}

see: http://play.golang.org/p/BQjqUsf9aU

答案5

得分: 0

使用实现了Reverse()方法的自定义类型是另一种选择。

package main

import "fmt"

type (
	MapA map[string]string
	MapB map[int]string
)

// Reverse返回MapA对象的反向映射。
func (m MapA) Reverse() map[string]string {
	n := make(map[string]string, len(m))
	for k, v := range m {
		n[v] = k
	}
	return n
}

// Reverse返回MapB对象的反向映射。
func (m MapB) Reverse() map[string]int {
	n := make(map[string]int, len(m))
	for k, v := range m {
		n[v] = k
	}
	return n
}

func main() {
	myMapA := &MapA{
		"apple":  "likey",
		"orange": "no likey",
	}
	myMapB := &MapB{
		10: "likey",
		5:  "not sure",
		0:  "no likey",
	}

	fmt.Println(myMapA.Reverse())
	fmt.Println(myMapB.Reverse())
}
英文:

Using a custom type with a Reverse() method implemented is another option.

package main
import &quot;fmt&quot;
type (
MapA map[string]string
MapB map[int]string
)
// Reverse returns a reverse map of the MapA object.
func (m MapA) Reverse() map[string]string {
n := make(map[string]string, len(m))
for k, v := range m {
n[v] = k
}
return n
}
// Reverse returns a reverse map of the MapB object.
func (m MapB) Reverse() map[string]int {
n := make(map[string]int, len(m))
for k, v := range m {
n[v] = k
}
return n
}
func main() {
myMapA := &amp;MapA{
&quot;apple&quot;:  &quot;likey&quot;,
&quot;orange&quot;: &quot;no likey&quot;,
}
myMapB := &amp;MapB{
10: &quot;likey&quot;,
5:  &quot;not sure&quot;,
0:  &quot;no likey&quot;,
}
fmt.Println(myMapA.Reverse())
fmt.Println(myMapB.Reverse())
}

答案6

得分: 0

扩展@Dave C的答案,使用泛型

package main

import (
	"fmt"
)

func main() {

	myMap := map[int]string{
		1: "one",
		2: "two",
		3: "three",
	}

	result := reverseMap(myMap)
	fmt.Println(result)

}

func reverseMap[M ~map[K]V, K comparable, V comparable](m M) map[V]K {
	reversedMap := make(map[V]K)
	for key, value := range m {
		reversedMap[value] = key
	}
	return reversedMap
}
英文:

Extending @Dave C's answer , with generic

package main
import (
&quot;fmt&quot;
)
func main() {
myMap := map[int]string{
1: &quot;one&quot;,
2: &quot;two&quot;,
3: &quot;three&quot;,
}
result := reverseMap(myMap)
fmt.Println(result)
}
func reverseMap[M ~map[K]V, K comparable, V comparable](m M) map[V]K {
reversedMap := make(map[V]K)
for key, value := range m {
reversedMap[value] = key
}
return reversedMap
}

huangapple
  • 本文由 发表于 2014年4月21日 11:19:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/23190311.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定