Golang中更简洁高效提取map中共同和唯一元素的方法

Golang中更简洁高效提取map中共同和唯一元素的方法

package main

import "fmt"

func main() {
	fmt.Println("vim-go")

	firstMap := map[string]string{
		"first":    "Pritesh",
		"middle":   "Manohar",
		"last":     "Ugrankar",
		"city":     "Bangalore",
		"building": "Ittina Neela",
	}
	secondMap := map[string]string{
		"first":    "Pritesh",
		"middle":   "Manohar",
		"last":     "Ugrankar",
		"location": "ECity",
	}

	common, unique := unique(firstMap, secondMap)
	fmt.Println("First map contains:", firstMap)
	fmt.Println("Second map contains:", secondMap)
	fmt.Println("Common elements are:", common)
	fmt.Println("Unique elements are:", unique)
}

func unique(first map[string]string, second map[string]string) (map[string]string, map[string]string) {
	commonMap := make(map[string]string)
	uniqueMap := make(map[string]string)

	for key, _ := range first {
		uniqueMap[key] = first[key]
	}
	for key, _ := range second {
		if _, ok := uniqueMap[key]; ok == true {
			delete(uniqueMap, key)
			commonMap[key] = second[key]
		} else {
			uniqueMap[key] = second[key]
		}
	}

	return commonMap, uniqueMap
}

运行结果如下:

pritesh@debian:~/go/src/github.com/pritesh-ugrankar/umaps$ go run main.go
vim-go
First map contains: map[building:Ittina Neela city:Bangalore first:Pritesh last:Ugrankar middle:Manohar]
Second map contains: map[first:Pritesh last:Ugrankar location:ECity middle:Manohar]
Common elements are: map[first:Pritesh last:Ugrankar middle:Manohar]
Unique elements are: map[building:Ittina Neela city:Bangalore location:ECity]
pritesh@debian:~/go/src/github.com/pritesh-ugrankar/umaps$ 

我对代码中的以下部分有疑问:

for key, _ := range second {
		if _, ok := uniqueMap[key]; ok == true {
			delete(uniqueMap, key)
			commonMap[key] = second[key]
		} else {
			uniqueMap[key] = second[key]

问题是如果我移除"else"循环,那么第二个映射中的唯一键就不会被添加到唯一映射中。我尝试了各种方法,但只有这个方案有效,而且这看起来真的很丑陋,像是一个拙劣的变通方案。

如何改进它呢?


更多关于Golang中更简洁高效提取map中共同和唯一元素的方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

8 回复

看到你们高效的解答后,我觉得自己的问题和回答都显得很笨拙。嘿嘿嘿嘿。

更多关于Golang中更简洁高效提取map中共同和唯一元素的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


特别感谢您提出的问题,这些问题促使我思考并学到了更多……图片

感谢Yamil的解答和耐心指导。 这对我来说真是"该死,为什么我就没想到这样思考"的时刻。 从您的回答中学到的东西,远比任何书籍或视频都要多。

确实。在提问之后,我尝试自己解决这个问题,并编写了几乎相同的代码,只是我使用了 ok == false 而不是 !ok(两者含义相同,只是语法不同)。

再次感谢您,先生。

func main() {
    fmt.Println("hello world")
}

好的。

唯一需要检查的是从第一个映射到第二个映射,我的意思是,我们只检查了元素是否在第一个映射中而不在第二个映射中,但反之则没有做。

在 unique 函数返回映射之前,只需添加以下代码:

// Now search for elements only in second mao and not in first map
	for key, value := range second {
	   if _, ok := first[key]; !ok {
	     uniqueMap[key] = value
	   }
	}
	
	return commonMap, uniqueMap

我喜欢 Go 语言的地方在于它以简洁为驱动力(实验、简化、发布
你可以通过类似以下方式来简化你的函数:

func unique(first map[string]string, second map[string]string) (map[string]string, map[string]string) {
	commonMap := make(map[string]string)
	uniqueMap := make(map[string]string)
	
	for key, value := range first {
	   // 检查是否唯一
	   if   _, ok := second[key]; ok {
	      // 存在于第二个映射中,因此是共有的
	     commonMap[key] = value
	    } else {
	      // 不存在于第二个映射中,是唯一的
	      uniqueMap[key] = value
	    }
	}

	return commonMap, uniqueMap
}

我尝试了你粘贴的代码,但它遗漏了一些值: 以下是代码(我已注释掉我的代码并输入了你的代码):

package main

import "fmt"

func main() {
	fmt.Println("vim-go")

	firstMap := map[string]string{
		"first":    "Pritesh",
		"middle":   "Manohar",
		"last":     "Ugrankar",
		"city":     "Bangalore",
		"building": "Ittina Neela",
	}
	secondMap := map[string]string{
		"first":    "Pritesh",
		"middle":   "Manohar",
		"last":     "Ugrankar",
		"location": "ECity",
	}

	common, unique := unique(firstMap, secondMap)
	fmt.Println("First map contains:", firstMap)
	fmt.Println("Second map contains:", secondMap)
	fmt.Println("Common elements are:", common)
	fmt.Println("Unique elements are:", unique)
}

func unique(first map[string]string, second map[string]string) (map[string]string, map[string]string) {
	commonMap := make(map[string]string)
	uniqueMap := make(map[string]string)

	/*
		for key, _ := range first {
			uniqueMap[key] = first[key]
		}
		for key, _ := range second {
			if _, ok := uniqueMap[key]; ok == true {
				delete(uniqueMap, key)
				commonMap[key] = second[key]
			} else {
				uniqueMap[key] = second[key]
			}
		}
	*/
	for key, value := range first {
		// Check if unique or not
		if _, ok := second[key]; ok {
			// Exists in second, so it is common
			commonMap[key] = value
		} else {
			// Does not exist in secodn, it is unique
			uniqueMap[key] = value
		}
	}
	return commonMap, uniqueMap
}

输出结果是:

pritesh@debian:~/go/src/github.com/pritesh-ugrankar/umaps$ go run main.go
vim-go
First map contains: map[building:Ittina Neela city:Bangalore first:Pritesh last:Ugrankar middle:Manohar]
Second map contains: map[first:Pritesh last:Ugrankar **location:ECity** middle:Manohar]
Common elements are: map[first:Pritesh last:Ugrankar middle:Manohar]
Unique elements are: map[building:Ittina Neela city:Bangalore]

请注意,location:ECity 条目缺失了。(我在代码输出中用加粗标出了它)。

以下是改进后的代码,使用更简洁高效的方法来提取map中的共同和唯一元素:

package main

import "fmt"

func main() {
    firstMap := map[string]string{
        "first":    "Pritesh",
        "middle":   "Manohar",
        "last":     "Ugrankar",
        "city":     "Bangalore",
        "building": "Ittina Neela",
    }
    secondMap := map[string]string{
        "first":    "Pritesh",
        "middle":   "Manohar",
        "last":     "Ugrankar",
        "location": "ECity",
    }

    common, unique := unique(firstMap, secondMap)
    fmt.Println("First map contains:", firstMap)
    fmt.Println("Second map contains:", secondMap)
    fmt.Println("Common elements are:", common)
    fmt.Println("Unique elements are:", unique)
}

func unique(first, second map[string]string) (map[string]string, map[string]string) {
    commonMap := make(map[string]string)
    uniqueMap := make(map[string]string)
    
    // 先处理第一个map的所有元素
    for k, v := range first {
        uniqueMap[k] = v
    }
    
    // 处理第二个map,区分共同和唯一元素
    for k, v := range second {
        if _, exists := uniqueMap[k]; exists {
            // 如果存在于uniqueMap中,说明是共同元素
            commonMap[k] = v
            delete(uniqueMap, k)  // 从uniqueMap中移除
        } else {
            // 否则是第二个map中的唯一元素
            uniqueMap[k] = v
        }
    }
    
    return commonMap, uniqueMap
}

更简洁的版本,使用单个循环处理逻辑:

func unique(first, second map[string]string) (map[string]string, map[string]string) {
    commonMap := make(map[string]string)
    uniqueMap := make(map[string]string)
    
    // 复制第一个map到uniqueMap
    for k, v := range first {
        uniqueMap[k] = v
    }
    
    // 处理第二个map
    for k, v := range second {
        if _, inFirst := uniqueMap[k]; inFirst {
            commonMap[k] = v
            delete(uniqueMap, k)
        } else {
            uniqueMap[k] = v
        }
    }
    
    return commonMap, uniqueMap
}

使用更函数式的写法:

func unique(first, second map[string]string) (common, unique map[string]string) {
    common = make(map[string]string)
    unique = make(map[string]string)
    
    // 初始化unique为第一个map的副本
    for k, v := range first {
        unique[k] = v
    }
    
    // 处理第二个map
    for k, v := range second {
        if _, exists := unique[k]; exists {
            common[k] = v
            delete(unique, k)
        } else {
            unique[k] = v
        }
    }
    return
}

这些改进版本保持了相同的逻辑,但代码更加清晰易懂。关键点在于:

  • 使用更简洁的变量命名
  • 移除不必要的_占位符
  • 保持相同的算法复杂度O(n+m),其中n和m分别是两个map的大小
  • 使用命名返回值使代码更易读

运行结果与原始代码相同,但代码结构更加优雅。

回到顶部