close

Python當中最重要的資料結構應該算是list跟dictionary了。要存取list內部的元素,傳統上都是使用index:假設有一個list叫做a,長度為10則它的所有元素為a[0], a[1], a[2], ..., a[8], a[9]。Python除了傳統的index外,又提供了一個像瑞士小刀一樣的東西叫slice,本篇稍微介紹一下slice的威力。

slice的語法是:a[m:n],代表從第m個元素開始取,取到第n-1個元素為止。不過slice的用途遠大於存取元素,它還可以存取「看不見的東西」,這樣講是有點毛毛的。不過,要真正了解slice的威力,或許不要從「元素」的角度來看,而是從「位置」的角度來看。如果我們將list當中,元素之間的空隙(最前面跟最後面也算)也標上數字,大概是這個樣子:P0, a[0], P1, a[1], P2, a[2], P3, ..., P8, a[8], P9, a[9], P10。則a[m:n]就代表從第m個位置開始取,取到第n個位置為止。m跟n可以都出現,可以只出現其一,也可以都不出現。a[m:]指的是第m個位置到最後面,a[:n]指的是最前面到第n個位置,a[:]指的是最前面到最後面,其實就等同於a本身,但注意到只是「值」的相等。

如果我們寫:

a=[0,1,2,3,4]

b=a

c=a[:]

則b跟a都指向同一個address,當a的內容改變,b的內容跟著變,但c是指向另一個address,因此當a的內容改變,c還是等於[0,1,2,3,4]。

有了這個觀念,接下來討論list的彈性,list可以取代/增加/刪除/排序(sort)/逆轉(reverse),此處我只針對取代/增加/刪除,因為排序跟逆轉剛好就有兩個同名的method可以用。

一、用slice來取代元素

我們先講index的取代。若a=[0,1,2,3,4],m=2,n=4:

元素被元素所取代:a[m]=p,取代之後a變成[0,1,p,3,4]

元素被list所取代:a[n]=(p,q),取代之後a變成[0,1,p,3,(p,q)]

注意到list可以容許不同資料型態做為它的元素,因此這裡的p,q可以是數字或字串,甚至是另一個list (p,q)。

用slice來做取代,寫法大同小異,但其功能更強大,且沒有規定取代者或是被取代者的長度,也就是說,取代完之後的list,長度可能不變(跟用index來做取代一樣),但也可能變長或變短。上述兩個例子,我們用slice來做:

a[m:m+1]=(p),取代之後a變成[0,1,p,3,4]

a[n:n+1]=(p,q),取代之後a變成[0,1,p,3,p,q]

我們發現,此時(p,q)成為a的兩個元素,而非一個做為a的元素的list,跟前面用index來做會得到不一樣的結果。a的長度變成6,增加了1。同樣地,若我們寫:

a[n:n+2]=(r),取代之後a變成[0,1,p,3,r],原本的(p,q)被(r)所取代。

二、用slice來增加元素

index有其限制:我們無法存取看不見的東西。slice的出現彌補了這個缺憾,用slice來處理取代更具有靈活性。list的增加刪減,都可以化約為取代。我們舉例如下:

如果a=[0,1,2,3,4]

則a[:0]=(p),取代之後a變成[p,0,1,2,3,4]

則a[len(a):]=(q),取代之後a變成[p,0,1,2,3,4,q]

其實前者就相當於insert(0,p),後者就相當於insert(len(a),q)或是append(q)。

由於slice必須視為一種sub-list,因此後面對應到的(p)跟(q)都必須以list的形式來表示。

聰明的你一定馬上知道,插入的值可以是好幾個元素,不妨試試看以下的assignment:

a[:0]=(p,q,r)

a[len(a):]=(s,t,u)

前者在Python中無對應的method,只能一次insert一個元素,後者就相當於extend((s,t,u))。

若要在特定位置插入一到多個元素,可以這樣寫:

a[m:m]=(p,q,r,...)

這個寫法比insert(m,x)來得強,因為insert一次只能插入一個元素,而用slice來寫,隨便你要插入幾個元素都沒問題。

這裡再補充一點,如果我們將list看做一個集合,則index只是取當中的一個元素,其地位就是一個元素。但slice是取零個到多個元素,其地位是一個集合,更明確來說,它是list的一個子集合(subset)。

三、用slice來刪除元素

要將一個到多個元素刪除,用slice來做很簡單:

a[m:n]=()

所以如果寫:

a=[0,1,2,3,4]

a[2:4]=()

我們會得到:

a=[0,1,4]

同樣地,Python內建了一個method,叫做pop(),但pop()每次只能刪除一個元素,好處是它會回傳該元素的值。若不需知道欲刪除元素的值,則使用slice比較方便。

總之,雖然Python已經內建了許多處理list的method,但功能都有限。若能熟悉slice的用法,則「吾道一以貫之」,可以用這把瑞士刀做許多事情。

 

 

arrow
arrow
    全站熱搜

    hambao 發表在 痞客邦 留言(3) 人氣()