[英]PowerShell Remove item [0] from an array
我很難刪除數組的第一行(項目 ID)。
$test.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
要列出我嘗試過的所有選項,$test | gm
,$test | gm
,它明確指出:
Remove Method void IList.Remove(System.Object value)
RemoveAt Method void IList.RemoveAt(int index)
所以當我嘗試$test.RemoveAt(0)
我得到錯誤:
Exception calling "RemoveAt" with "1" argument(s): "Collection was of a fixed size."At line:1 char:1
+ $test.RemoveAt(1)
+ ~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : NotSupportedException
所以我終於在這里發現我的數組需要是System.Object
類型才能使用$test.RemoveAt(0)
。 將腳本開頭的所有 arrays 聲明為列表是最佳做法嗎? 還是稍后在需要此功能時將帶有$collection = ({$test}.Invoke())
的 arrays 轉換為列表更好?
兩種類型的優缺點是什么? 謝謝您的幫助。
另一種選擇是使用 Powershell 分配多個變量的能力(請參閱其他答案)。
$arr = 1..5
$first, $rest= $arr
$rest
2
3
4
5
十多年來,它一直是 Powershell 的一個功能。 我從MSDN 博客文章中發現了此功能:
數組是固定大小的,就像錯誤所說的那樣。 RemoveAt()
是一種不適用於普通數組的繼承方法。 要刪除數組中的第一個條目,您可以通過包含除第一個之外的所有項目的副本覆蓋數組,如下所示:
$arr = 1..5
$arr
1
2
3
4
5
$arr = $arr[1..($arr.Length-1)]
$arr
2
3
4
5
如果您需要刪除不同索引處的值,那么您應該考慮使用List
。 它支持Add()
、 Remove()
和RemoveAt()
:
#If you only have a specific type of objects, like int, string etc. then you should edit `[System.Object] to [System.String], [int] etc.
$list = [System.Collections.Generic.List[System.Object]](1..5)
$list
1
2
3
4
5
$list.RemoveAt(0)
$list
2
3
4
5
有關數組如何工作的更多詳細信息,請參閱我之前的SO 答案和about_Arrays 。
這將允許您從數組中刪除每個出現的任意元素,而無需求助於更復雜的 .NET 對象。
$x=<array element to remove>
$test = $test | Where-Object { $_ -ne $x }
或者,
$x=<array index to remove>
$test = $test | Where-Object { $_ -ne $test[$x] }
這將執行相同的操作,但只會刪除其中一個元素。 如果有重復,它們將保留。 這也可以通過上面的索引樣式來完成。
$x=<array element to remove>
$skip=$true
$test = $test | ForEach-Object { if (($_ -eq $x) -and $skip) { $skip=$false } else { $_ } }
同樣基於其中一條評論,如果您不確定$test
是一個數組,那么將$test=@($test)
放在首位可能是明智的。
您可以使用Select-Object -Skip <count>
來省略第一個計數項:
PS C:\> 1..3 | Select-Object -Skip 1
2
3
PS C:\>
PS C:\> 1 | Select-Object -Skip 1
PS C:\>
我認為這將取決於具體情況。 如果您只需要刪除第一個元素一次,那么您可以使用數組切片:
$arr = $arr[1..($arr.length-1)]
如果您要重復執行此操作,則應從數組列表或泛型集合開始。 如果它是一個大數組,您可能只想將創建它的表達式放入腳本塊中並對其執行 .invoke(),而不是讓管道創建一個數組,然后將其轉換為集合。
removeat() 適用於數組列表(如 $error):
[collections.arraylist]$a = get-process
$a.removeat(0)
有一種更簡單優雅的方法可以做到這一點。 該答案也適用於具有單個元素的 arrays(與之前給出的其他一些答案不同)。 它也適用於任何所需的索引。
$arr = @(1,2,3)
$arr -ne $arr[0] #remove first element: @(2,3)
$arr -ne $arr[1] #remove second element: @(1,3)
$arr -ne $arr[-1] #remove last element: @(1,2)
請原諒我遲到的答案,但我也在為此苦苦掙扎。 出於我的意圖和目的(寫入文本文件),我意識到由於數組是固定大小——而不是刪除它,我可以將值設置為 string.empty。
$results = SQLQuery -connectionString $connectionString -query $query;
$results[0] = '';
foreach ($r in $results) {
Add-Content $skus $r[0];
}
對我來說,這擺脫了我在平面文件中不想要的標題。 希望這可以幫助其他人。
如果我們遇到必須由某些部分執行大數組(或 ArrayList)的情況 - 我使用了一些生活技巧:
#$bigArray with thousands of items
while($bigArray.Count -gt 0)
{
if($bigArray.Count -gt 100)
{
$k = 100
}else {$k = $bigArray.Count}
$part = $bigArray | select -First $k
#now we can make some operations with this $part
#in the end of loop we should exclude this part from big array
if($bigArray.Count -gt 100)
{
$bigArray = $bigArray | select -Last ($bigArray.Count - $k)
}else {$bigArray = @()}#in this step we have been handle last part of array and we should null him for stop loop
}
現在我們可以按某些部分(按 100 個項目)處理大數組
將其他答案與我的小改動相結合(將其用作 $profile 中的全局函數):
function global:sudo {
$runArgs = $args
if($runArgs.Length -le 1) {
$runArgs = ""
}
else {
$runArgs = $runArgs[1..($runArgs.length - 1)]
$runArgs = $runArgs -join " "
}
Start-Process $args[0] -ArgumentList $runArgs -Verb runas
}
因此, sudo notepad
和sudo notepad c:\\windows\\abc.txt
都可以使用,並且應該優雅地傳遞參數(雖然沒有真正徹底檢查)
如果要刪除已知索引 x(基數為 0)的一行,也可以只復制數組的下部和上部。
從 arry 中刪除行 x
$LastElement = $arry.GetUpperBound(0)
if ($LastElement -ge 0) {
if ($x -eq 0) {
$lowerRange = @()
} else {
$lowerRange = @($arry[0..($x-1)])
}
if ($x -eq $LastElement) {
$upperRange = @()
} else {
$upperRange = @($arry[($x+1)..$LastElement])
}
$arry = @($lowerRange; $upperRange)
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.