Nim教程【九】

liulun發表於2015-06-15

向關注這個系列的朋友們,道一聲:久違了!

它並沒有被我閹掉,他一定會得善終的,請各位不要灰心


Set集合型別

為了在特殊場景下提高程式的效能設定了Set型別,同時也是為了保證效能,所以Set只能容納有序型別,

Set型別可以被一個大括號例項化:

var x = {},x就是一個空的set型別

還可以在大括號構造符號內部填寫set變數內部的元素,或一組元素

就像下面的程式碼一樣

type
  CharSet = set[char]
var
  x: CharSet
x = {'a'..'z', '0'..'9'}

可以用於Set型別的操作符

操作符含義
A + Bunion操作,連結兩個Set變數
A * B得到兩個集合的交集
A - B得到兩個集合的差異(A中哪些元素是B所不包含的)
A == B
判斷兩個集合是否相等
A <= BA是否與B相等或者A是否是B的子集
A < BA是否是B的子集
e in AA包含元素e
e notin AA不包含元素e
contains(A,e)A包含元素e
Card(A)
A中包含多少個元素
incl(A,e)
與A = A +  {e}相同
excl(A,e)與A = A - {e}相同

Array陣列型別

陣列是一個固定長度的容器

陣列中的每個元素必須型別相同

陣列可以使用方括號構造

請看下面的程式碼

type
  IntArray = array[0..5, int] # an array that is indexed with 0..5
var
  x: IntArray
x = [1, 2, 3, 4, 5, 6]
for i in low(x)..high(x):
  echo(x[i])

程式碼中x[i]的意思是訪問陣列x的第i個元素

nim語言會對陣列訪問執行邊界檢查

你通過開關的形式來設定:到底是在編譯期執行邊界檢查,還是在執行期執行邊界檢查

(譯註:我們這裡就不講怎麼設定這個開關了)

陣列是值型別的,像其他值型別一樣,賦值操作將複製整個陣列內容

len方法返回陣列的長度

low方法返回陣列的最小下標

high方法返回陣列的最大下標

請仔細看一下下面的程式碼:

type
  Direction = enum
    north, east, south, west
  BlinkLights = enum
    off, on, slowBlink, mediumBlink, fastBlink
  LevelSetting = array[north..west, BlinkLights]
var
  level: LevelSetting
level[north] = on
level[south] = slowBlink
level[east] = fastBlink
echo repr(level)  # --> [on, fastBlink, slowBlink, off]
echo low(level)   # --> north
echo len(level)   # --> 4
echo high(level)  # --> west

可以用多個方括號來實現多維陣列

在多維陣列中,不同的緯度可以擁有不同的索引型別

來看一下下面的程式碼

type
  Direction = enum
    north, east, south, west
  BlinkLights = enum
    off, on, slowBlink, mediumBlink, fastBlink
  LevelSetting = array[north..west, BlinkLights]
  LightTower = array[1..10, LevelSetting]
var
  tower: LightTower
tower[1][north] = slowBlink
tower[1][east] = mediumBlink
echo len(tower)     # --> 10
echo len(tower[1])  # --> 4
echo repr(tower)    # --> [[slowBlink, mediumBlink, ...more output..
# The following lines don't compile due to type mismatch errors
#tower[north][east] = on
#tower[0][1] = on

注意:len(tower)只返回第一維陣列的長度

我們還可以通過下面的方式定義多維陣列,(可讀性更好一些)

type
  LightTower = array[1..10, array[north..west, BlinkLights]]

還有一種簡單的定義陣列的方法,來看看下面的程式碼

type
  IntArray = array[0..5, int] # an array that is indexed with 0..5
  QuickArray = array[6, int]  # an array that is indexed with 0..5
var
  x: IntArray
  y: QuickArray
x = [1, 2, 3, 4, 5, 6]
y = x
for i in low(x)..high(x):
  echo(x[i], y[i])

從上面的程式碼中可以看出,定義陣列的時候,不必每次都要指定陣列的最小下標

seq序列型別

seq型別類似於陣列,但seq型別可以在執行期改變容器的長度;

也正是因為seq是長度可變的,所以nim在記憶體堆上為它分配空間和進行垃圾收集

seq型別的索引總是從0開始的,

len、low、high操作同樣適用於seq型別

可以通過x[i]訪問seq型別的x變數的第i個元素

seq型別可以通過@和方括號來構造,也可以使用內建的newSeq方法來構造

請看下面的程式碼

var
  x: seq[int] # a sequence of integers
x = @[1, 2, 3, 4, 5, 6] # the @ turns the array into a sequence

如果你沒有為一個seq型別的變數賦值,那麼它的預設值將為nil

在很多應用在seq變數的操作中,操作nil的話會丟擲異常

所以很多人都會為seq型別的變數設定空值:@[]

但是設定空值的話,會在記憶體堆上建立一個空序列

一定程度上有損效能

請你自行斟酌權衡吧

用for語句遍歷一個序列的時候,for語句中可以存在一個或兩個變數

如果是一個變數的時候,

這個變數將持有每次迭代過程中seq提供的值

如果是兩個變數的時候,

第一個變數將儲存索引的位置

第二個變數將儲存seq提供的值

請看下面的程式碼:

for i in @[3, 4, 5]:
  echo($i)
# --> 3
# --> 4
# --> 5

for i, value in @[3, 4, 5]:
  echo("index: ", $i, ", value:", $value)
# --> index: 0, value:3
# --> index: 1, value:4
# --> index: 2, value:5



今天就寫到這裡吧!

喜歡的人請幫忙點個推薦!



相關文章