一個網站的使用者管理中,一般使用者都會起一個昵稱,當然使用者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
<code>users := map[string]</code><code>int</code><code>{</code><code>"chen"</code><code>: 20, </code><code>"chen長"</code><code>: 10, </code><code>"春風"</code><code>: 5, </code><code>"龍ge"</code><code>: 13, </code><code>"where你are"</code><code>: 7}</code>
<code>var targetCount map[string]</code><code>int</code> <code>= make(map[string]</code><code>int</code><code>)</code>
<code>for</code> <code>name, count := range users {</code>
<code> </code><code>matched := </code><code>true</code>
<code> </code><code>for</code> <code>_, v := range name {</code>
<code> </code><code>if</code> <code>v < </code><code>'\u4e00'</code> <code>|| v > </code><code>'\u9fbf'</code> <code>{</code>
<code> </code><code>matched = </code><code>false</code>
<code> </code><code>break</code>
<code> </code><code>}</code>
<code> </code><code>}</code>
<code> </code><code>if</code> <code>matched {</code>
<code> </code><code>targetCount[name] = count</code>
<code>}</code>
<code>fmt.Println(targetCount)</code>
解釋一下:
第一層for循環周遊users集合,得到昵稱(name)和計數(count ):
for name, count := range users{
// ......
}
第二層循環周遊昵稱name字元串中的每個字元,并判斷是否有非中文字元:
for _, v := range name{
if v <'\u4e00' || v > '\u9fbf' { // 該範圍下的字元為非中文字元
}
【備注】:
這裡由變量matched充當了标志,當出現非中文字元時,matched被賦為false,并使用break中止第二層循環,然後判斷該name是否僅為中文,若是則添加進入targetCountw集合中。
運作結果為:map[春風:5]
§問題2. 從這個集合中找出隻包含中文的使用者昵稱的計數資訊,但發現第一個非全中文的使用者昵稱的時候就停止查找。
這裡涉及到map類型的特性問題,當使用for進行周遊users集合時,順序會出現不确定性,即第一個昵稱有可能是“chen”,也有可能是“春風”,也有可能是“龍ge”,總之是不确定的。
假設第一個昵稱是“chen長”時,程式發現它是非全中文的昵稱,這時整個程式需要結束。
<code> </code><code>if</code> <code>!matched {</code>
<code> </code><code>break</code>
<code> </code><code>} </code><code>else</code> <code>{</code>
這個程式實作與上面基本是大同小異,不同之處在于第一層循環中的matched判斷。
假設在第一層for循環中,第一次取到的昵稱name為“龍ge”,此時第二層for循環中會逐個字元地檢視“龍ge”這個字元串,當程式發現“龍ge”是非全中文時,matched标志被置為false,同時跑出第二層循環,然後在第一層循環中問:“取到的昵稱‘龍ge’是否為全中文?”,結果不是,于是按照題目要求就break掉程式并時跳出第一層循環。
這裡如果您多運作一下程式,就會發現結果有可能是不同的,有時為map[],有時為map[春風:5]
§問題3. 不使用輔助辨別(如上例中的matched)解決§問題2.
作者這裡是讓您學習break Label這個東東,是以這裡直接引用作者原話了:“我們之前說過,break語句可以與标記(Label)語句一起配合使用。”
<code>L:</code>
<code> </code><code>for</code> <code>name, count := range users {</code>
<code> </code><code>for</code> <code>_, v := range name {</code>
<code> </code><code>if</code> <code>v < </code><code>'\u4e00'</code> <code>|| v > </code><code>'\u9fbf'</code> <code>{</code>
<code> </code><code>break</code> <code>L</code>
<code> </code><code>}</code>
該程式與§問題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語句後面那些語句(它們被跳過了)。
<code> </code><code>continue</code>
<code> </code><code>targetCount[name] = count</code>
或者
<code> </code><code>for</code> <code>name,count := range users{</code>
<code> </code><code>for</code> <code>_, v := range name{</code>
<code> </code><code>if</code> <code>r < </code><code>'\u4e00'</code> <code>|| r > </code><code>'\u9fbf'</code><code>{</code>
<code> </code><code>continue</code> <code>L</code>
OK,在讀這個章節時,隻是感覺這個例子有點意思,是以分享給大家 :)
本文轉自qingkechina 51CTO部落格,原文連結:http://blog.51cto.com/qingkechina/1983333,如需轉載請自行聯系原作者