我正在努力消除数组的第一行(项目ID)。
$test.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
列出我尝试,$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
所以我终于发现here我的数组必须属于System.Object
类型才能使用$test.RemoveAt(0)
。最佳做法是将脚本开头的所有数组声明为列表吗?或者,如果需要此功能,最好将带有$collection = ({$test}.Invoke())
的数组转换为列表?
这两种类型的专业和缺点是什么?谢谢你的帮助。
答案 0 :(得分:19)
数组是固定大小的,就像错误所说的那样。 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 answer和about_Arrays。
答案 1 :(得分:10)
这将允许您从数组中删除每个出现的任意元素,而无需使用更复杂的.NET对象。
$x=<array element 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 { $_ } }
答案 2 :(得分:8)
另一种选择是使用Powershell分配多个变量的能力(请参阅https://docs.microsoft.com/en-gb/powershell/module/microsoft.powershell.core/about/about_assignment_operators?view=powershell-5.1上的分配多个变量,这要归功于此答案:https://stackoverflow.com/a/37733801)。
$arr = 1..5
$first, $rest= $arr
$rest
2
3
4
5
十多年来,它一直是Powershell的功能。我从以下博客文章中发现了此功能:https://blogs.msdn.microsoft.com/powershell/2007/02/05/powershell-tip-how-to-shift-arrays/
答案 3 :(得分:7)
您可以使用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:\>
答案 4 :(得分:3)
只是为了更新 - @Frode F. answer
存在问题如果数组中的元素数量超过1
$arr = $arr[1..($arr.Length-1)]
如果元素的数量是1,那么这不会删除元素
if($arr.Length -le 1) {
$arr = @()
}
else {
$arr = $arr[1..($arr.length - 1)]
}
答案 5 :(得分:2)
我认为这取决于具体情况。如果您只需要删除第一个元素一次,那么您可以使用数组切片:
$arr = $arr[1..($arr.length-1)]
如果你要重复这样做,那么你应该从一个arraylist或泛型集合开始。如果它是一个大型数组,您可能只想将创建它的表达式放入一个scriptblock并对其执行.invoke(),而不是让管道创建一个数组,然后将其转换为一个集合。
答案 6 :(得分:0)
原谅迟到的回答,但我也在努力解决这个问题。为了我的意图和目的(写入文本文件),我意识到由于数组是固定大小 - 而不是删除它我可以将值设置为string.empty。
{{1}}
对我来说,这摆脱了我在平面文件中不想要的标题。希望这有助于其他人。
答案 7 :(得分: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项)
答案 8 :(得分:0)
removeat()可用于数组列表(例如$ error):
[collections.arraylist]$a = get-process
$a.removeat(0)
答案 9 :(得分:0)
将其他答案与我的小改动相结合(将其用作 $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
都可以工作,并且应该优雅地传递参数(虽然没有真正彻底检查)
答案 10 :(得分:0)
如果要删除已知索引 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)
}