【golang】map遍历注意事项

结论

for循环中三个表达式:
for initialization; condition; post { }
初始initialization只会评估一次,后续更新表达式值将不起作用,但post可以实现更新

  • map 循环判断某个元素是否存在时常出现下面问题
go 复制代码
for _, ok1 := numsSet[num+1]; ok1; {
	...
	更新num值,但ok1的值不会被更新,死循环
}
---------------------------------------------------------
for _, ok := m[num]; ok; _, ok = m[num] {
	更新num值,ok在for循环第三个表达式中被跟新,可以实现功能
}
-----------------------------------------------------------
for _, ok := m[num]; ok; {
	...
	// 内部手动更新也可以,关键点就是ok这个循环遍历只在第一次遍历的时候创建并评估
	_, ok = m[num]  
}

问题分析

使用for循环遍历判断某个元素是否存在,会存在一定的问题

对 for _, ok1 := numsSet[num+1]; ok1; {...} 这行代码的问题分析:

错误分析:

  • 在 Go 语言中,for 语句的迭代子句可以有以下几种形式:
    • for initialization; condition; post { } // 初始initialization只会评估一次,后续更新表达式值将不起作用,但post可以更新
    • for condition { }
    • for { }

当 you 尝试使用 for _, ok1 := numsSet[num+1]; ok1; {...} 时,存在以下错误:

  • 即使 you 正确接收了这两个值,如 _, ok1 := numsSet[num+1],for 循环的条件部分 ok1 只会在循环开始时被评估一次,而不会在每次迭代后重新评估(因此想着通过函数内部修改num,再评估一次_, ok1 := numsSetnum+1是不可行的),因此无法实现循环的正确终止条件。

正确写法1 :利用for循环第三个表达式,更新第二个判断条件

核心在于:for _, ok := m[num]; ok; _, ok = m[num] {...}

go 复制代码
func findContinueNum2(nums []int) int {
	m := map[int]struct{}{}

	for _, val := range nums {
		m[val] = struct{}{}
	}

	res := 1
	for k, _ := range m {
		curRes := 1
		// 每个key验证
		if _, exist := m[k-1]; !exist {
			// 第一个数,统计最长
			num := k + 1
			for _, ok := m[num]; ok; _, ok = m[num] {
				curRes++
				res = max(res, curRes)
				num++
			}
		}
	}
	return res
}

正确写法2:

go 复制代码
package main

func findContinueNum2(nums []int) int {
    numsSet := map[int]struct{}{}
    for _, val := range nums {
       numsSet[val] = struct{}{}
    }
    res := 1
    for k := range numsSet {
       curRes := 1
       if _, ok := numsSet[k-1];!ok {
          // 第一个数,起点
          num := k
          for {
             _, ok1 := numsSet[num+1]
             if!ok1 {
                break
             }
             curRes++
             res = max(curRes, res)
             num++
          }
       }
    }
    return res
}

func max(a, b int) int {
    if a > b {
       return a
    }
    return b
}

代码解释:

  • 在 findContinueNum2 函数中,首先创建了一个 map[int]struct{} 来存储 nums 切片中的元素。
  • 然后遍历 numsSet 中的键。
    • 当 k-1 不在 numsSet 中时,将 k 作为连续序列的起始元素。
    • 接着进入一个无限 for 循环,在每次迭代中,使用 _, ok1 := numsSet[num+1] 来检查 num+1 是否在 numsSet 中。
      • 如果 ok1 为 false,使用 break 终止内部的 for 循环。
      • 否则,更新 curRes 的值并将 num 加 1。
  • max 函数用于比较 curRes 和 res 的大小,返回较大的值。

使用示例:

go 复制代码
func main() {
    nums := []int{1, 2, 3, 5, 6, 7, 9, 10, 11}
    result := findContinueNum2(nums)
    println(result)
}

代码解释:

  • 在 main 函数中,定义了一个整数切片 nums。
  • 调用 findContinueNum2 函数并将结果存储在 result 中。
  • 最后打印结果。

上述代码通过修正后的 for 循环结构,能够正确处理连续元素的查找和计数,避免了原代码中 for 循环使用不当的问题。

相关推荐
白帽攻防录26 分钟前
SRC 挖洞:PostScript 打印机驱动双 RCE,打印服务器怎么变成内网跳板
开发语言·网络安全·php·内网安全
十年Java程序媛41 分钟前
Java枚举Enum完整教程|替代静态常量,开发与面试要点
java·开发语言·spring boot·后端·面试
2603_965148111 小时前
电商选品调研:通过关键词搜索API获取市场热销商品,结合商品详情API分析竞品卖点与定价
开发语言·数据库·人工智能·python·信息可视化
生态学者2 小时前
Global Change Biology | 森林越“步调一致”,反而越怕干旱?树木生长与叶片活动的同步之谜
大数据·人工智能·算法·r语言·微信公众平台
xixiaoyunya2 小时前
Python 异步编程入门:用 asyncio 轻松实现并发任务
开发语言·python·php
lsswear2 小时前
Agent 框架新手入门与实战部署指南
大数据·人工智能·算法
学逆向的2 小时前
C 循环结构的执行效率分析
c语言·开发语言·数据结构·网络安全
小坏讲微服务3 小时前
刚发布一个月的JDK 27,为什么我建议你立刻升级?
java·开发语言·spring boot·spring·架构·求职招聘·springboot4
Data analyse4564 小时前
rnweb 回放数据量太大怎么办?分片存储与断点续传的实现思路
前端·网络·算法·数据分析
打工仔折腾 AI4 小时前
用 Dashlet 把极空间 NAS 服务入口整理成统一导航首页的实践
java·开发语言·人工智能·后端·python·rpc·ai agent 实战