[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#在幫我們處理而已,當然,之前提及過,腳本就要有腳本的樣子,自動化才是關注的重點~~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM