如何初始化自定义对象数组 [英] How to initialize an array of custom objects

查看:66
本文介绍了如何初始化自定义对象数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,由于这引出了我的问题,我首先要指出的是,我已经在 PowerShell 中使用了相当多的 XML,并且喜欢如何快速地将 XML 文件中的数据读取到自定义对象数组中.例如,如果我有以下 XML 文件:

First, as this leads to my question, I'll start by noting that I've worked with XML a fair bit in PowerShell, and like how I can read data from XML files, quickly, into arrays of custom objects. For example, if I had the following XML file:

<stuff>
 <item name="Joe" age="32">
  <info>something about him</info>
 </item>
 <item name="Sue" age="29">
  <info>something about her</info>
 </item>
 <item name="Cat" age="12">
  <info>something else</info>
 </item>
</stuff>

如果我简单地阅读它,就像这样:

And if I read it in simply, like this:

[xml]$myxml = Get-Content .\my.xml

然后我可以像这样访问我的项目数组:

Then I can get to an array of my items like this:

[array]$myitems = $myxml.stuff.Item
$myitems

name   age  info
----   ---  ----
Joe    32   something about him
Sue    29   something about her
Cat    12   something else

那么,现在我的问题是:

So, now my question:

如何在不读取文件的情况下创建自定义对象数组的类似结构,并在脚本中初始化它们?

我可以进行大量循环和/或大量创建/初始化单个对象,然后一次将一个添加到数组中...

I can do lots of looping and/or lots of creating/initializing individual objects, and then add to an array one at a time...

但似乎应该有一种方法可以以更简单的方式执行此创建/初始化.请注意,这里的关键是我的自定义对象有两个以上的元素(否则,我会使用哈希).

But it seems there should be a way to perform this creation/initialization in a simpler way. Note that the key here, is that my custom objects have more than two elements (otherwise, I'd have used a hash).

我什至考虑过创建一大串 XML 并使用 Select-XML,但我就是无法获得正确的语法(如果那是正确的前进方向的话).

I've even looked at creating a big string of XML, and using Select-XML, but I just couldn't get the syntax right (if that was even the right road to be heading down).

推荐答案

我会做一些类似的事情:

I'd do something along these lines:

$myitems =
@([pscustomobject]@{name="Joe";age=32;info="something about him"},
[pscustomobject]@{name="Sue";age=29;info="something about her"},
[pscustomobject]@{name="Cat";age=12;info="something else"})

请注意,这仅适用于 PowerShell 3,但由于您没有在问题中提及版本,我假设这对您来说无关紧要.

Note that this only works in PowerShell 3, but since you did not mention the version in your question I'm assuming this does not matter for you.

更新

评论中已经提到,如果您执行以下操作:

It has been mentioned in comments that if you do the following:

$younger = $myitems | Where-Object { $_.age -lt 20 } 
Write-Host "people younger than 20: $($younger.Length)" 

您不会像预期的那样获得 1.当返回单个 pscustomobject 时会发生这种情况.现在这对于 PowerShell 中的大多数其他对象都不是问题,因为它们具有 LengthCount 的代理属性.不幸的是 pscustomobject 没有.这已在 PowerShell 6.1.0 中修复.您可以使用运算符 @() 解决此问题:

You won't get 1 as you might expect. This happens when a single pscustomobject is returned. Now this is not a problem for most of other objects in PowerShell, because they have surrogate properties for Length and Count. Unfortunately pscustomobject does not. This is fixed in PowerShell 6.1.0. You can work around this by using operator @():

$younger = @($myitems | Where-Object { $_.age -lt 20 })

有关更多背景信息,请参阅此处此处.

For more background see here and here.

更新 2

在 PowerShell 5 中可以使用 来实现类似的功能.例如,您可以像这样定义一个类:

In PowerShell 5 one can use Classes to acheive similar functionality. For example you can define a class like this:

class Person {
    [string]$name
    [int]$age
    [string]$info; `
`
    Person(
    [string]$name,
    [int]$age,
    [string]$info
    ){
        $this.name = $name
        $this.age = $age
        $this.info = $info
    }
}

这里的反引号是为了您可以将其复制并粘贴到命令行,脚本中不需要它们.一旦定义了类,您就可以按照通常的方式创建一个数组:

Backticks here are so that you could copy and paste it to the command line, they are not required in a script. Once the class is defined you can the create an array the usual way:

$myitems =@([Person]::new("Joe",32,"something about him"),
[Person]::new("Sue",29,"something about her"),
[Person]::new("Cat",12,"something else"))

请注意,即使在 PowerShell 5 中,这种方式也没有之前更新中提到的缺点.

Note that this way does not have the drawback mentioned in the previous update, even in PowerShell 5.

更新 3

您还可以使用哈希表初始化类对象,类似于第一个示例.为此,您需要确保定义了默认构造函数.如果您不提供任何构造函数,则会为您创建一个,但如果您提供一个非默认构造函数,则默认构造函数将不存在,您需要明确定义它.这是自动创建的默认构造函数的示例:

You can also intialize a class object with a hashtable, similar to the first example. For that you need to make sure that a default contructor defined. If you do not provide any constructors, one will be created for you, but if you provide a non-default one, default constructor won't be there and you will need to define it explicitly. Here is an example with default constructor that is auto-created:

class Person {
    [string]$name
    [int]$age
    [string]$info;
}

有了它,您可以:

$person = @([Person]@{name='Kevin';age=36;info="something about him"}
[Person]@{name='Sue';age=29;info="something about her"}
[Person]@{name='Cat';age=12;info="something else"})

这有点冗长,但也更明确.感谢@js2010 指出这一点.

This is a bit more verbose, but also a bit more explicit. Thanks to @js2010 for pointing this out.

这篇关于如何初始化自定义对象数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆