【问题标题】:Add an array to an array list将数组添加到数组列表
【发布时间】:2023-04-02 11:25:03
【问题描述】:

好的,我将把问题改写为更通用和更完整。但我将原始帖子留在底部。

给定:一个变量$queue,我想向其中添加不同种类和大小的集合,这些集合可以是本地创建的变量,也可以是从函数传递的结果。 在处理$queue 时,我想避免+=,因此不能选择简单的数组。 我需要能够添加可变大小的集合,因此需要支持.AddRange(),因为它可以处理单个项目集合和更大的集合。 我需要支持 Windows 7/PS2 以及 Windows 10/PS5 [System.Collections.ArrayList] 已被弃用,所以这并不理想。 这使得System.Collections.Generic.List[string] 成为$queue 的类型 此外,我需要添加到$queue 的大多数地方可能最多有几百个,但可能有超过 1000 个地方定义了各种其他集合。因此,让所有其他集合也使用System.Collections.Generic.List[string] 将是非常有问题的。即使只是在返回之前进行铸造也是一项繁重的工作。所以我真的想在$queue.AddRange() 内进行干预。 这也是一个短期重构和错误修复版本(一些错误与这些东西有关),在彻底重写为类之前,其中 100% 的这些集合将是System.Collections.Generic.List[string],并且会少很多冗余代码。 此外,现在希望获得最简单、最易读的代码,以使重写尽可能容易。

所以,理想情况下这是可行的

$queue = New-Object System.Collections.Generic.List[string]

$array1 = @('array1.1')
$array3 = @('array3.1', 'array3.2', 'array3.3')
$arrayList1 = [System.Collections.ArrayList]@('arrayList1.1')
$arrayList3 = [System.Collections.ArrayList]@('arrayList3.1', 'arrayList3.2', 'arrayList3.3')
$genericList1 = [System.Collections.Generic.List[string]]@('genericList1.1')
$genericList3 = [System.Collections.Generic.List[string]]@('genericList3.1', 'genericList3.2', 'genericList3.3')

function ReturnArray ([int]$count) {
    $return = @()
    foreach ($i in 1..$count) {
        $return += "ArrayFunction$($count).$($i)"
    }
    return $return
}

function ReturnArrayList ([int]$count) {
    $return = New-Object System.Collections.ArrayList
    foreach ($i in 1..$count) {
        $return.Add("ArrayListFunction$($count).$($i)") > $null
    }
    return $return
}

function ReturnGenericList ([int]$count) {
    $return = New-Object System.Collections.Generic.List[string]
    foreach ($i in 1..$count) {
        $return.Add("GenericList[string]Function$($count).$($i)")
    }
    return $return
}

CLS
$queue.AddRange($array1)
$queue.AddRange($array3)

$queue.AddRange($arrayList1)
$queue.AddRange($arrayList3)

$queue.AddRange($genericList1)
$queue.AddRange($genericList3)

$returnValue = ReturnArray 1
$queue.AddRange($returnValue)
$returnValue = ReturnArray 3
$queue.AddRange($returnValue)

$returnValue = ReturnArrayList 1
$queue.AddRange($returnValue)
$returnValue = ReturnArrayList 3
$queue.AddRange($returnValue)

$returnValue = ReturnGenericList 1
$queue.AddRange($returnValue)
$returnValue = ReturnGenericList 3
$queue.AddRange($returnValue)

$queue

这在许多方面都存在问题。当从函数返回单个元素数组时,它会展开,因此.AddRange() 不起作用。但我想避免像这样重新排列所有内容

$queue.AddRange(@($variable))

在 Windows 10 中,像这样将所有内容都转换为 [System.Collections.Generic.List[string]],并且使用类型加速器甚至可以读取。但这在 Windows 7/PS2 中失败。

$queue.AddRange([System.Collections.Generic.List[string]]$array1)
$queue.AddRange([System.Collections.Generic.List[string]]$array3)

$queue.AddRange([System.Collections.Generic.List[string]]$arrayList1)
$queue.AddRange([System.Collections.Generic.List[string]]$arrayList3)

$queue.AddRange([System.Collections.Generic.List[string]]$genericList1)
$queue.AddRange([System.Collections.Generic.List[string]]$genericList3)

$returnValue = ReturnArray 1
$queue.AddRange([System.Collections.Generic.List[string]]$returnValue)
$returnValue = ReturnArray 3
$queue.AddRange([System.Collections.Generic.List[string]]$returnValue)

$returnValue = ReturnArrayList 1
$queue.AddRange([System.Collections.Generic.List[string]]$returnValue)
$returnValue = ReturnArrayList 3
$queue.AddRange([System.Collections.Generic.List[string]]$returnValue)

$returnValue = ReturnGenericList 1
$queue.AddRange([System.Collections.Generic.List[string]]$returnValue)
$returnValue = ReturnGenericList 3
$queue.AddRange([System.Collections.Generic.List[string]]$returnValue)

所以,简而言之,问题是;是否有一种单一的、可读的、高性能的方法可以在 Win7/PS2 和 Win10/PS5 中进行这项工作?令人沮丧的是,似乎使用[System.Collections.ArrayList] 实际上更容易一些。但是,在弃用和.Add() 污染管道之间,这发生在很多函数中,这也不是一种选择。

希望这能澄清问题的范围。

原帖


我正在重构一些代码以使用通用列表与数组,因为一些数组变得越来越大,我更喜欢.Add().AddRange() 而不是+=

但是,我有很多代码,我可能无法一次重构所有内容。所以我会有一些地方需要将数组添加到数组列表中,有时数组来自函数。我的感觉是,目前最好的方法就是在我添加的位置将数组转换为数组列表,例如......

$list.AddRange([System.Collections.Generic.List[string]]$array)

然后,一旦我替换了简单数组使用的每个实例,我就可以返回清理不必要的强制转换。这是我最好的前进方式,还是我错过了更简单的答案?

此外,在相关说明中,在我看来,使用

定义我自己的类型加速器
$Accelerators = [PowerShell].Assembly.GetType("System.Management.Automation.TypeAccelerators")
$Accelerators::Add("PxStringList","System.Collections.Generic.List[string]")

可能是个好主意。自从

$list.AddRange([PxStringList]$array)

比阅读更容易

$list.AddRange([System.Collections.Generic.List[string]]$array)

再次,我是在正确的轨道上,还是遗漏了一些明显的东西?

编辑:如果有人想知道故障模式,这是对我提出问题的代码的 sn-p。这在 Windows 7 和 Windows 10 中失败。

$validFontExtentions = @('.ttf', '.txt')
$fontQueue = New-Object System.Collections.Generic.List[string]
$fontQueue.AddRange($validFontExtentions)

【问题讨论】:

  • 问题是什么?
  • @mathias-r-jessen,问题是,当我执行 AddRange 时进行强制转换是处理可能添加的数组的最佳方式吗?正如 JosefZ 指出的那样,可以展开您添加的任何内容,但我的感觉是该案例更具可读性,并且是短期需求。但即使是短期解决方案,我也不想做对。
  • $fontQueue.AddRange([System.Collections.Generic.IEnumerable[string]]$validFontCollection)
  • @JosefZ,Generic.ListGeneric.IEnumerable 有什么区别?我见过的例子都只提到了List。好吧,或者他们提到[arralylist],我听说它已被弃用,所以我也试图避免这种情况。
  • 如果 $listArrayLIst 没关系 - 另一方面,如果 $list 是通用集合,它通常会接受任何 IEnumerable<T>,包括平面数组,所以你可以使用$list.AddRange([string[]]$array),或者如果你不知道类型参数:$list.AddRange($array -as "$($list.GetType().GenericTypeArguments[0])[]")。不过,我仍然不清楚问题是什么,我们要在这里解决的确切问题是什么?

标签: arrays powershell arraylist casting


【解决方案1】:

如果我理解了您的问题陈述,您基本上希望将现有列表或数组添加到另一个列表中,而不必一次枚举并添加一个。我遇到了同样的问题,用下面的方法解决了。

TL/DR:使用 ArrayList 和 += 运算符代替 .Add

PS C:\WINDOWS\system32> $arr1 = ("a","b","c")
PS C:\WINDOWS\system32> $arr1
a
b
c
PS C:\WINDOWS\system32> $arr2 = ("d","e","f")
PS C:\WINDOWS\system32> $arr2
d
e
f
PS C:\WINDOWS\system32> $arrList = new-object System.Collections.ArrayList
PS C:\WINDOWS\system32> $arrList.Add($arr1)
0    <=== CLUE

这里有个线索:.Add 的输出只有一个索引,尽管我们知道应该添加 3 个元素。

PS C:\WINDOWS\system32> $arrList
a
b
c

但是当你输出 arraylist 时,它看起来像 3 个元素。

PS C:\WINDOWS\system32> $arrList | % {"another one: $_"}
another one: a b c

但是当您使用 foreach 进行迭代时,很明显您添加了一个带有空格的元素。

但如果你使用 +=,你会看到数组实际上是一次添加一项。

PS C:\WINDOWS\system32> $arrList2 = new-object System.Collections.ArrayList
PS C:\WINDOWS\system32> $arrList2 += $arr1
PS C:\WINDOWS\system32> $arrList2
a
b
c
PS C:\WINDOWS\system32> $arrList2 | % {"another one: $_"}
another one: a
another one: b
another one: c
PS C:\WINDOWS\system32> $arrList2 += $arr2
PS C:\WINDOWS\system32> $arrList2 | % {"another one: $_"}
another one: a
another one: b
another one: c
another one: d
another one: e
another one: f

这里我们向 ArrayList2 添加了两个不同的数组,每个数组包含 3 个元素,结果是一个包含 6 个单独元素的列表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-27
    • 1970-01-01
    • 1970-01-01
    • 2013-09-24
    • 2014-03-25
    • 1970-01-01
    相关资源
    最近更新 更多