504*_*ore 2 arrays powershell arraylist generic-list
为什么.NET Framework ArrayList类.Add方法在PowerShell实现中不起作用?
除非我另外纠正,否则我认为我的故事的整体道德可能是:不要假设本机PowerShell方法将与.NET方法相同,并且在PowerShell中尝试.NET方法时要小心.
我正在寻找的原始解决方案是从一个函数返回一个日期列表,作为一个数组,用户定义的日期范围作为参数.然后引用日期数组来移动和读取以日期戳命名的文件.
我遇到的第一个问题是创建一个动态数组.我不知道我在做什么,并且错误地.Add
在@()
数组声明上调用.NET 方法.
使用"1"参数调用"Add"的异常:"Collection具有固定大小."
我认为我需要找到一个动态数组类型,当我真正的问题是我做得不对时.这让我走向了一个不同的方向,直到很久以后,我发现应该使用+=
语法将对象添加到PowerShell数组中.
无论如何,在我回到如何正确使用PowerShell数组之前,我在其他一些切线上了.
然后我找到了.NET ArrayList
类.好的.现在我有一个动态数组对象.我阅读了文档,其中说我应该使用该.Add
方法向集合中添加元素.
然后开始寻求更深入的理解,因为我经历了几天头脑紧张的挫折试图解决问题.
我制作了一个最初工作的实现.它产生了一个日期范围 - 但它也产生了一些奇怪的行为.我观察到奇怪的日期返回,例如:
0001年1月1日星期一12:00:00 AM
事实证明,我发现这是你执行此操作时获得的结果:
Get-Date 0
Run Code Online (Sandbox Code Playgroud)
该ArrayList
被返回时,首先,索引值的数组元素的列表,然后将数组值.这根本没有任何意义.我开始探索我是否正确地调用函数,我是否遇到某种可变范围问题,或者我是否只是疯了.
我现在相当确信我的挫败感是由于缺乏一个可靠的初学者参考,不仅仅展示了如何进行简单数组实现的几个例子,而是用其他解决方案描述了一些注意事项.
让我在这里解释一下,实现数组/集合的三种方法,以及我试图生成的解决方案 - 即日期范围内的日期列表.
出于某种原因,我最初认为在Powershell中向.NET ArrayList添加元素的正确方法是使用.Add方法.它的记载.我仍然不明白为什么这不起作用(严重 - 有人请赐教).通过实验,我发现通过使用+=
将对象添加到ArrayList 的方法,我可以获得准确的结果.
不要这样做.这绝对是错的.它会产生我上面描述的错误:
Function Get-DateRangeList {
[cmdletbinding()]
Param (
[datetime] $startDate,
[datetime] $endDate
)
$datesArray = [System.Collections.ArrayList]@() # Second method
for ($d = $startDate; $d -le $endDate; $d = $d.AddDays(1)) {
if ($d.DayOfWeek -ne 'Sunday') {
$datesArray.Add($d)
}
}
Return $datesArray
}
# Get one week of dates, ending with yesterday's date
$startDate = Get-Date
$endDate = $startDate.AddDays(-1) # Get yesterday's date as last date in range
$startDate = $endDate.AddDays(-7) # Get 7th prior date as first date in range
$datesList = Get-DateRangeList $startDate $endDate
# Loop through the dates
Foreach ($d in $datesList) {
# Do something with each date, e.g., format the date as part of a list
# of date-stamped files to retrieve
$d
}
Run Code Online (Sandbox Code Playgroud)
现在,下面有三个代码示例,DO WORK.在每个示例中,代码都是相同的.我所做的就是对相应的实例化行和方法行进行注释/取消注释.
首先,使用本机PowerShell数组对象:
Function Get-DateRangeList {
[cmdletbinding()]
Param (
[datetime] $startDate,
[datetime] $endDate
)
$datesArray = @() # First method
#$datesArray = [System.Collections.ArrayList]@() # Second method
#$datesArray = New-Object System.Collections.Generic.List[System.Object] # Third method
for ($d = $startDate; $d -le $endDate; $d = $d.AddDays(1)) {
if ($d.DayOfWeek -ne 'Sunday') {
$datesArray += $d # First and second method: += is the method to add elements to: Powershell array; or .NET ArrayList (confusing)
#$datesArray.Add($d) # Third method: .Add is the method to add elements to: .NET Generic List
}
}
Return $datesArray
}
# Get one week of dates, ending with yesterday's date
$startDate = Get-Date
$endDate = $startDate.AddDays(-1) # Get yesterday's date as last date in range
$startDate = $endDate.AddDays(-7) # Get 7th prior date as first date in range
$datesList = Get-DateRangeList $startDate $endDate
# Loop through the dates
Foreach ($d in $datesList) {
# Do something with each date, e.g., format the date as part of a list
# of date-stamped files to retrieve
"FileName_{0}.txt" -f $d.ToString("yyyyMMdd")
}
Run Code Online (Sandbox Code Playgroud)
其次,使用.NET FrameworkArrayList
:
Function Get-DateRangeList {
[cmdletbinding()]
Param (
[datetime] $startDate,
[datetime] $endDate
)
#$datesArray = @() # First method
$datesArray = [System.Collections.ArrayList]@() # Second method
#$datesArray = New-Object System.Collections.Generic.List[System.Object] # Third method
for ($d = $startDate; $d -le $endDate; $d = $d.AddDays(1)) {
if ($d.DayOfWeek -ne 'Sunday') {
$datesArray += $d # First and second method: += is the method to add elements to: Powershell array; or .NET ArrayList (confusing)
#$datesArray.Add($d) # Third method: .Add is the method to add elements to: .NET Generic List
}
}
Return $datesArray
}
# Get one week of dates, ending with yesterday's date
$startDate = Get-Date
$endDate = $startDate.AddDays(-1) # Get yesterday's date as last date in range
$startDate = $endDate.AddDays(-7) # Get 7th prior date as first date in range
$datesList = Get-DateRangeList $startDate $endDate
# Loop through the dates
Foreach ($d in $datesList) {
# Do something with each date, e.g., format the date as part of a list
# of date-stamped files to retrieve
"FileName_{0}.txt" -f $d.ToString("yyyyMMdd")
}
Run Code Online (Sandbox Code Playgroud)
第三,使用.NET Framework通用列表:
Function Get-DateRangeList {
[cmdletbinding()]
Param (
[datetime] $startDate,
[datetime] $endDate
)
#$datesArray = @() # First method
#$datesArray = [System.Collections.ArrayList]@() # Second method
$datesArray = New-Object System.Collections.Generic.List[System.Object] # Third method
for ($d = $startDate; $d -le $endDate; $d = $d.AddDays(1)) {
if ($d.DayOfWeek -ne 'Sunday') {
#$datesArray += $d # First and second method: += is the method to add elements to: Powershell array; or .NET ArrayList (confusing)
$datesArray.Add($d) # Third method: .Add is the method to add elements to: .NET Generic List
}
}
Return $datesArray
}
# Get one week of dates, ending with yesterday's date
$startDate = Get-Date
$endDate = $startDate.AddDays(-1) # Get yesterday's date as last date in range
$startDate = $endDate.AddDays(-7) # Get 7th prior date as first date in range
$datesList = Get-DateRangeList $startDate $endDate
# Loop through the dates
Foreach ($d in $datesList) {
# Do something with each date, e.g., format the date as part of a list
# of date-stamped files to retrieve
"FileName_{0}.txt" -f $d.ToString("yyyyMMdd")
}
Run Code Online (Sandbox Code Playgroud)
所有这三项工作.为什么你喜欢一个而不是另一个?本机PowerShell数组和.NET Framework ArrayList
类都生成非强类型对象的集合,因此您可以执行此操作(在Powershell数组实现中):
$myArray = @(1, 2, 3, "A", "B", "C")
Run Code Online (Sandbox Code Playgroud)
对于非常大的阵列,Powershell阵列效率不高.对于非常大的集合,ArrayList是更好的选择.
对于非常大的同类型对象集合,.NET Framework通用列表似乎是最佳选择.在我的例子中,我想要一个日期列表.每个日期都是相同的数据类型,因此我不需要混合对象类型.因此,我正在部署的解决方案是上面的第三个工作示例.
我很欣赏Dave Wyatt 2013年关于该主题的Powershell.org文章:PowerShell性能:+ =运算符(以及何时避免它).特别是,该+=
方法在循环内的每个传递中创建一个新的数组对象,添加新元素,然后销毁旧数组.对于大型集合,这变得非常低效.
我发布这些解决方案和讨论,希望其他初学者能更容易找到我想要的答案.
是的 - 这是对的 - 我不坚持某些人的想法是严格的PowerShell语法礼仪.我return
在函数中使用了该语句,因此很明显函数产生了什么.我更喜欢可读代码,这些代码可能看起来庞大而不是紧张.这是我的偏好,我坚持认为.
对于更多PowerShell式的日期列表实现,我向读者推荐The Surly Admin发布的整洁实现.
大多数时候我看到阵列添加,这是完全没必要的.每当表达式返回多个对象时,Powershell管道将自动为您创建数组,并且它将非常有效地执行.
考虑:
Clear-Host
Function Get-DateRangeList {
[cmdletbinding()]
Param (
[datetime] $startDate,
[datetime] $endDate
)
$datesArray =
for ($d = $startDate; $d -le $endDate; $d = $d.AddDays(1)) {
if ($d.DayOfWeek -ne 'Sunday') {
$d
}
}
Return ,$datesArray
}
# Get one week of dates, ending with yesterday's date
$startDate = Get-Date
$endDate = $startDate.AddDays(-1) # Get yesterday's date as last date in range
$startDate = $endDate.AddDays(-7) # Get 7th prior date as first date in range
$datesList = Get-DateRangeList $startDate $endDate
# Loop through the dates
Foreach ($d in $datesList) {
# Do something with each date, e.g., format the date as part of a list of date-stamped files to retrieve
“FileName_{0}.txt" -f $d.ToString("yyyyMMdd")
}
Run Code Online (Sandbox Code Playgroud)
所需要的只是创建和输出您的对象,并将结果分配回您的变量,您将拥有一个数组.
归档时间: |
|
查看次数: |
899 次 |
最近记录: |