博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
读《Go并发编程实战》第4章 流程控制方式
阅读量:6515 次
发布时间:2019-06-24

本文共 3025 字,大约阅读时间需要 10 分钟。

   一个网站的用户管理中,一般用户都会起一个昵称,当然用户A和用户B的昵称有可能相同,我们就使用类型为map[string]int的集合来表示,其中string代表用户昵称、int表示昵称相同的人数。

       集合数据内容为:{"chen":20,   "chen长":10,   "春风":5,   "龙ge":13,   "where你are":7}。

§问题1. 从这个集合中找出只包含中文的用户昵称的计数信息

    上面集合中只有用户昵称为“春风”的元素满足条件,其它像“龙ge”、“chen长”、“where你are”都不是只包含中文。像看程序实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
users := map[string]
int
{
"chen"
: 20, 
"chen长"
: 10, 
"春风"
: 5, 
"龙ge"
: 13, 
"where你are"
: 7}
var targetCount map[string]
int 
= make(map[string]
int
)
 
for 
name, count := range users {
    
matched := 
true
    
for 
_, v := range name {
        
if 
v < 
'\u4e00' 
|| v > 
'\u9fbf' 
{
            
matched = 
false
            
break
        
}
    
}
    
if 
matched {
        
targetCount[name] = count
    
}
}
fmt.Println(targetCount)

解释一下:

第一层for循环遍历users集合,得到昵称(name)和计数(count ):

for namecount := range users{

      // ......

}

第二层循环遍历昵称name字符串中的每个字符,并判断是否有非中文字符:

for _, := range name{

      if v <'\u4e00' || v > '\u9fbf' {  // 该范围下的字符为非中文字符

      }

}

【备注】:

    这里由变量matched充当了标志,当出现非中文字符时,matched被赋为false,并使用break中止第二层循环,然后判断该name是否仅为中文,若是则添加进入targetCountw集合中。

运行结果为:map[春风:5]

§问题2. 从这个集合中找出只包含中文的用户昵称的计数信息,但发现第一个非全中文的用户昵称的时候就停止查找

    这里涉及到map类型的特性问题,当使用for进行遍历users集合时,顺序会出现不确定性,即第一个昵称有可能是“chen”,也有可能是“春风”,也有可能是“龙ge”,总之是不确定的。

    假设第一个昵称是“chen长”时,程序发现它是非全中文的昵称,这时整个程序需要结束。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
for 
name, count := range users {
    
matched := 
true
    
for 
_, v := range name {
        
if 
v < 
'\u4e00' 
|| v > 
'\u9fbf' 
{
            
matched = 
false
            
break
        
}
    
}
    
if 
!matched {
        
break
    
else 
{
        
targetCount[name] = count
    
}
}
fmt.Println(targetCount)

    这个程序实现与上面基本是大同小异,不同之处在于第一层循环中的matched判断。

    假设在第一层for循环中,第一次取到的昵称name为“龙ge”,此时第二层for循环中会逐个字符地查看“龙ge”这个字符串,当程序发现“龙ge”是非全中文时,matched标志被置为false,同时跑出第二层循环,然后在第一层循环中问:“取到的昵称‘龙ge’是否为全中文?”,结果不是,于是按照题目要求就break掉程序并时跳出第一层循环。

    这里如果您多运行一下程序,就会发现结果有可能是不同的,有时为map[],有时为map[春风:5]

§问题3. 不使用辅助标识(如上例中的matched)解决§问题2.

    作者这里是让您学习break Label这个东东,所以这里直接引用作者原话了:“我们之前说过,break语句可以与标记(Label)语句一起配合使用。

1
2
3
4
5
6
7
8
9
L:
    
for 
name, count := range users {
        
for 
_, v := range name {
            
if 
v < 
'\u4e00' 
|| v > 
'\u9fbf' 
{
                 
break 
L
            
}
        
}
        
targetCount[name] = count
    
}

该程序与§问题2程序功能是相同的,只是把标志matched移除掉了。

    一条标记语句可以成为goto语句、break语句和contiune语句的目标。标记语句中的标记只是一个标识符,它可以被置在任何语句的左边以作为这个语句的标签。标记和被标记的语句之间需要用冒号“:”来分隔,即如下所示:

L:

     for name, count := range users{

          // .....

     }

    需要注意的是,标记L也是一个标识符,那么当它在未被使用的时候同样也会报告编译错误。那么怎么使用呢?一种方法就是让它成为break的目标,即上面示例中的break L。

    标签L代码块包含了第一层for循环,第一层for循环包含了第二层for循环,所以当break L时,它是中止整个标签L代码块,所以这里会中止两层for循环。

 对比“§问题2”和“§问题3”的两个代码实现,“§问题3”的代码更简洁一些。

§问题4.  还是解决问题1的事情,只不过要求使用continue语句,即从这个集合中找出只包含中文的用户昵称的计数信息

由于这里没有更多的知识点,所以引用原文:

    实际上,Go语言中的continue语句只能在for语句中使用。continue语句会使直接包含它的那个for循环直接进入下一次迭代,换言之,本次迭代不会执行该continue语句后面那些语句(它们被跳过了)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
for 
name, count := range users {
    
matched := 
true
    
for 
_, v := range name {
        
if 
v < 
'\u4e00' 
|| v > 
'\u9fbf' 
{
            
matched = 
false
            
break
        
}
    
}
 
    
if 
!matched {
       
continue
    
}
    
targetCount[name] = count
}

或者

1
2
3
4
5
6
7
8
9
L:
    
for 
name,count := range users{
        
for 
_, v := range name{
            
if 
r < 
'\u4e00' 
|| r > 
'\u9fbf'
{
                
continue 
L
            
}
        
}
        
targetCount[name] = count
    
}

OK,在读这个章节时,只是感觉这个例子有点意思,所以分享给大家 :)

     本文转自qingkechina 51CTO博客,原文链接:http://blog.51cto.com/qingkechina/1983333,如需转载请自行联系原作者

你可能感兴趣的文章
PHP获取Cookie模拟登录CURL(转)
查看>>
PHP-权限控制类(转)
查看>>
CSS3秘笈第三版涵盖HTML5学习笔记9~12章
查看>>
bzoj1044木棍分割
查看>>
leetcode-136-Single Number
查看>>
http服务器小项目
查看>>
一些数学上的名词及操作
查看>>
Flume 读取实时更新的日志文件
查看>>
HDU 2049
查看>>
《Spring1之第十次站立会议》
查看>>
Unity Shader 噪声消融特效 - 剑灵死亡特效
查看>>
Eclipse 自动生成 Ant的Build.xml 配置文件
查看>>
添加一条信息到列表,如果重复就替换,
查看>>
C#基础第五天
查看>>
python 小数相加报错 invalid literal for int() with base 10
查看>>
【ubuntu】linux链接库
查看>>
uva 12325 枚举暴力 b
查看>>
多线程问题(JVM重排序)
查看>>
LeetCode 459 Repeated Substring Pattern
查看>>
POJ 3268 Silver Cow Party
查看>>