Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays Powershell阵列:何时使用它们;何时避免它们;以及使用它们的问题_Arrays_Powershell_Arraylist_Generic List - Fatal编程技术网

Arrays Powershell阵列:何时使用它们;何时避免它们;以及使用它们的问题

Arrays Powershell阵列:何时使用它们;何时避免它们;以及使用它们的问题,arrays,powershell,arraylist,generic-list,Arrays,Powershell,Arraylist,Generic List,为什么.NET Framework ArrayList类.Add方法不能在PowerShell实现中工作 除非我被纠正,否则我认为我的故事的整体寓意可能是:不要假设本机PowerShell方法将与.NET方法相同,在PowerShell中尝试.NET方法时要小心 我寻求的最初解决方案是以数组的形式从函数返回日期列表,并将用户定义的日期范围作为参数。然后将引用日期数组来移动和读取以日期戳命名的文件 我遇到的第一个问题是创建动态数组。我不知道自己在做什么,并且在@()数组声明上错误地调用了.NET.

为什么.NET Framework ArrayList类.Add方法不能在PowerShell实现中工作

除非我被纠正,否则我认为我的故事的整体寓意可能是:不要假设本机PowerShell方法将与.NET方法相同,在PowerShell中尝试.NET方法时要小心

我寻求的最初解决方案是以数组的形式从函数返回日期列表,并将用户定义的日期范围作为参数。然后将引用日期数组来移动和读取以日期戳命名的文件

我遇到的第一个问题是创建动态数组。我不知道自己在做什么,并且在
@()
数组声明上错误地调用了.NET
.Add
方法

使用“1”参数调用“Add”时出现异常:“集合大小固定。”

我认为我需要找到一个动态数组类型,而我真正的问题是我做得不对。这给了我一个不同的方向,直到很久以后,我才发现应该使用
+=
语法将对象添加到PowerShell数组中

无论如何,在我回到如何正确使用PowerShell阵列之前,我已经开始了一些其他方面的工作

然后我找到了.NET
ArrayList
类。好的,很好。现在我有了一个动态数组对象。我阅读了文档,其中说我应该使用
.Add
方法向集合中添加元素

然后,我开始寻求更深层次的理解,因为我经历了几天的沮丧,试图解决问题

我制作了一个一开始似乎可以工作的实现。它产生了一个日期范围,但也产生了一些奇怪的行为。我注意到返回了一些奇怪的日期,例如:

0001年1月1日星期一上午12:00:00

事实证明,我发现,这是当你这样做时得到的结果:

Get-Date 0
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
}
下面有三个代码示例。在每个示例中,代码都是相同的。我所做的就是注释/取消注释相应的实例化行和方法行

首先,使用本机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")
}
第二,使用:

第三,使用:

所有这三项工作。为什么你更喜欢一个而不是另一个?本机PowerShell数组和.NET Framework
ArrayList
类都会生成非强类型的对象集合,因此您可以这样做(在PowerShell数组实现中):

Powershell阵列对于非常大的阵列来说效率不高。对于非常大的集合,ArrayList是一个更好的选择

对于同一类型的大型对象集合,.NETFramework通用列表似乎是最佳选择。在我的示例中,我想要一个日期列表。每个日期都是相同的数据类型,因此我不需要混合对象类型。因此,我正在部署的解决方案是上面的第三个工作示例

我很欣赏Dave Wyatt在2013 Powershell.org上发表的关于以下主题的文章:。特别是
+=
方法,添加新元素,然后销毁旧数组。如果收集量很大,这将变得非常低效

我发布这些解决方案和讨论,希望其他初学者能更容易地找到我所寻求的答案

是的-没错-我不遵守某些人认为严格的PowerShell语法礼仪。我在函数中使用了
return
语句,因此很明显函数产生了什么。我更喜欢那些看起来杂乱无章而不是紧凑的可读代码。这是我的偏好,我会坚持下去


有关日期列表的更像PowerShell的实现,我建议读者参考。

大多数时候,我看到阵列添加时,完全没有必要。每当表达式返回多个对象时,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")
}

只需创建和输出对象,并将结果赋回变量,就可以得到一个数组。

关于OP:Collections的第3段。arraylist在powershell中工作,例如:

# Create arraylist with space for 20 object
$ar = new-object collections.arraylist 20
$ar.add("hello everybody")
$ar.add([datetime]::now)
$ar.add( (gps)[9])
$ar[0]  # returns string
$ar[1]  # returns datetime
$ar[2]  # returns tenth process
$ar.count # returns 3
我认为这样做的好处是更仔细地阅读arraylist的MSDN文档

如果在PS中的arraylist上使用+=,它将从arraylist中获取元素和新元素,并创建一个数组。我相信这是一种试图保护用户不受您偶然发现的.NET复杂性的影响的尝试。(我怀疑PS产品团队的一个主要用例是一个不是fami的用户
$myArray = @(1, 2, 3, "A", "B", "C")
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")
}
# Create arraylist with space for 20 object
$ar = new-object collections.arraylist 20
$ar.add("hello everybody")
$ar.add([datetime]::now)
$ar.add( (gps)[9])
$ar[0]  # returns string
$ar[1]  # returns datetime
$ar[2]  # returns tenth process
$ar.count # returns 3
# Fails because PS unrolls the array and thinks that each element is a
# different argument to String..ctor
$stringFromCharArray = new-object string $charArray
# Wrap $charArray to get it to work
$stringFromCharArray = new-object string @(,$charArray)
# This also works
$stringFromCharArray = new-object string (,$charArray)