首页 > 解决方案 > 数据行到字符串到数组问题

问题描述

我有一个非常奇怪的问题发生。我有一个填充了一堆行的对象。我可以很好地访问它们,但我需要附加一个“。” (dot) 到其中的每个值,所以我最终使用 for each 循环将每条记录转换为字符串并添加一个“。” 修剪值后。然而,现在的问题是,我想将这些行中的每一行(并且这些行只有一个列/项)分配给另一个数组/对象,以便以后可以访问它们。

问题是,即使我声明一个对象/数组变量并分配字符串转换的数据行,对象变量也会不断转换为字符串,我似乎无法避免它。

请帮忙。这是一个修改后的代码示例:

[String] $DBNms = @();

ForEach($DBName in $objDBNms){ 

   $tempText += $DBName.Item(0).ToString().Trim() + "."

   $DBNms += $tempText
}  

 Write-Host($DBNms.GetType()) #And this is showing up a string, while I want it to be an array.

如果我打印 $DBNms,它确实会显示一个字符串连接在一起成为一个字符串,而我实际上希望它像 $DBNms[0] = 第一个项目值,$DBNms[1] = 第二个项目值等等.

标签: arrayspowershellpowershell-5.0

解决方案


[String] $DBNms = @();由于类型文字被放置在variable的左侧,因此创建了$DBNms一个类型受限的变量,然后将其类型锁定为字符串;也就是说,作为单个字符串 [string]$DBNms

您正在寻找创建一个字符串数组,它在 PowerShell 中表示为[string[]]

[string[]] $DBNames = @()

PowerShell 的类型转换是自动的(并且非常灵活),因此[String] $DBNms = @()不会报告错误,它会悄悄地将空数组( @()) 转换为空字符串(根据类型约束的要求):

PS> [string] $DBNames = @(); '' -eq $DBNames
True

从数组中的多次迭代中收集值的一种更有效的方法是将foreach语句用作表达式,在这种情况下,PowerShell 会自动为您收集输出:

[string[]] $DBNms = foreach ($DBName in $objDBNms){ 

   # Output this expression's value as-is.
   # PowerShell will collect the individual iterations' values for you.
   $DBName.Item(0).ToString().Trim() + "."

}  

以上不仅比您原来的方法更简洁,更重要的是更有效:

  • 实际上,您不能直接添加(附加到)数组,因为它是不可变的数据结构。

  • 每当您使用+=数组时, PowerShell 必须做的是在幕后分配一个数组,复制原始元素并附加新元素;然后新数组会自动分配回变量。


注意:使用整个循环作为表达式的替代和下一个最佳解决方案是使用有效可扩展的列表类型,特别是[System.Collections.Generic.List[object]]( System.Collections.Generic.List`1):

# Create the list.
# The 'System.' namespace prefix is optional.
[Collections.Generic.List[string]] $DBNms = @()

foreach ($DBName in $objDBNms) { 

   # Add to the list, using its .Add() method.
   # Note: Do NOT try to add with +=
   $DBNms.Add($DBName.Item(0).ToString().Trim() + ".")

}  

如果您的循环不仅仅在每次迭代中输出单个值,例如需要附加到多个集合,您将需要这种方法。

注:以前常用System.Collections.ArrayList而是实例;然而:

  • 不再推荐使用此类型(请参阅链接帮助主题中的警告);使用[System.Collections.Generic.List[object]]代替,它还允许您对集合进行强类型[object]化(替换为感兴趣的类型,例如[string]上面的代码)。

  • 它的缺点是它的.Add()方法有一个返回值,您需要显式地将其静音(例如,$null = $lst.Add(...)),这样它就不会意外污染代码的输出流(产生意外的额外输出)。


推荐阅读