[Powershell] Powershell中的動態數組

This artical will also be published in English http://www.cnblogs.com/LarryAtCNBlog/p/4252464.html

又或者說是C#? 因爲powershell本源就是C#。當然,標題是個僞命題,根據如下MSDN頁所述,對於一個array對象來說,IsFixedSize屬性一直就是true的。

https://msdn.microsoft.com/en-us/library/system.array.isfixedsize(v=vs.110).aspx

換句說話就是array裏的成員對象數量是固定的,在powershell裏用如下的方法添加對象後實際上是複製了一份新數組,而打破了原有的地址指向。

$t = 1..2
$r = $t
$r[1] = 9
$t
# $t的輸出爲1, 9,因爲$r和$t實際上指向的同一個數據,類似於指針
######
$r += 10
$t
# $t的輸出依然會是1, 9,因爲後臺C#所做的實際上是複製了一份原有數組加入新的值後賦給了$r

這種數組添加方式真心簡單到爆,但是對資源的開銷大了不少,不過腳本嘛就要有腳本的樣子,簡單易用纔是正道。

但是如上面代碼裏所說,這種方法雖然簡單但是卻打破了原本$r和$t指向同一個數組的事實,原本我只需要改動$t或$r任一個裏的元素值,另一個也會跟着變化,但是這種添加元素的方法卻clone了一個新數組使得$t和$r指向了不同的指針。

有的時候真得非常需要兩個變量指向同一個數組指針一起更新數據,比如線程間的通信,但是元素數量的改動又是必須的,理所當然,會想到array本身可能有方法做這這個吧?事實是有,也同時沒有。看如下數組和對象的靜態方法,

Remove         Method                void IList.Remove(System.Object value)
RemoveAt       Method                void IList.RemoveAt(int index)
# 當使用remove和removeAt的時候會報錯說這個collection是fixed size的
Clear             Method     static void Clear(array array, int index, int length)
# 當使用[array]::clear($t, 1, 1)的時候的確可以清空最後一個元素的值,但是數組的成員數量依然不會改變

我想要的只是多個變量指向同一個數組且我能改變數組的成員數量並不影響前一條。

我之前一直關注在array對象上,想着會不會有什麼wonderful方法能直接實現我所想的,事實證明是錯誤的。於是我轉向了IsFixedSize這個屬性,想找一找有沒有其它對象足夠像array但是這個IsFixedSize屬性卻可以是false的,於是找到了ArrayList

https://msdn.microsoft.com/en-us/library/system.collections.arraylist(v=vs.110).aspx

$t = New-Object System.Collections.ArrayList
$t.IsFixedSize
# 輸出爲false

很好,第一步實現了,它是動態的,調用元素的方法也和普通array一樣。它填充元素的方法類似於hash table,感覺十分友好。

Add            Method                int Add(System.Object value), int IList.Add(System.Object v...
AddRange       Method                void AddRange(System.Collections.ICollection c)
Remove         Method                void Remove(System.Object obj), void IList.Remove(System.Ob...
RemoveAt       Method                void RemoveAt(int index), void IList.RemoveAt(int index)
RemoveRange    Method                void RemoveRange(int index, int count)
TrimToSize     Method                void TrimToSize()
Capacity       Property              int Capacity {get;set;}
Count          Property              int Count {get;}

Add是增加單個元素在數組的最後,AddRange則是把另一個Collection的對象複製到它的最後面,這就解決了元素增加的問題。

Remove* 的3個方法則是在數組中刪掉相應的元素,這解決了元素減少的問題。

Count和Capacity屬性會隨着元素增加而增長,但Capacity不會隨着元素減少而自減,Count屬性則會,這解決了元素Get and Set的問題。

TrimToSize也就是Align count和Capacity屬性,把該數組的capacity置於和count一樣。

至此,我之前想要的"多個變量指向同一個數組且我能改變數組的成員數量並不影響前一條"已經實現~~

那麼這種對象實現起來這麼容易,開銷呢?

無論從內存或者說是cpu來說開銷自然也是大不少的,最簡單的測試就是開倆powershell分別用這兩種辦法建一個大數組如1..1000000,然後就能從內存中看出明顯的佔用區別,至於CPU時間太短直觀的感覺不容易發現罷了。簡單易用的後臺是Powershell或者說C#在幫我們處理而已,當然,之前提及過,腳本就要有腳本的樣子,自動化纔是關注的重點~~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章