如何将哈希表添加到多维数组?无法通过成员枚举赋值
Posted
技术标签:
【中文标题】如何将哈希表添加到多维数组?无法通过成员枚举赋值【英文标题】:How to add hashtable to multidimensional array? Cannot assign values via member enumeration 【发布时间】:2018-08-24 02:56:03 【问题描述】:我在将哈希表添加到多维数组时遇到问题。我编写了以下代码:
$Data = @BIBs = @(
@$BIB = @BIBName=$BIBName,
@Standort = $Standort,
@Bücher = @(
@BuchName = $BuchName;
Autor = $Autor
)
)
此代码正在运行并创建一个输出,我将其存储在 JSON 中:
"BIBs": [
"BIB1": [
"BIBName": "123"
,
"Standort": "123"
,
"Bücher": [
"Autor": "123",
"BuchName": "123"
]
]
,
"BIB2": [
"BIBname": "345"
,
"Standort": "345"
,
"Bücher": [
"Autor": "345",
"Buchname": "345"
]
]
]
如您所见,我有额外的代码将另一个哈希表添加到数组“BIB”中。
$jsonfile = "C:\Skripte\bibV2-1000.json"
$Data = Get-Content $jsonfile | ConvertFrom-Json
$Data.BIBs += New-Object -TypeName PSObject -Property @
$BIB = @BIBname=$BIBName, @Standort=$Standort,
@Bücher = @(@Buchname=$BuchName;Autor=$Autor)
当输出如上所示时,我无法将另一个哈希表添加到“Bücher”。我用
检查了“Bücher”的类型$data.BIBs.BIB1.Bücher.GetType()
它实际上是一个数组:
IsPublic IsSerial 名称 BaseType -------- -------- ---- -------- 真真对象[] System.Array我试过了
$Data.BIBs.BIB1.Bücher += @Person="Max";Alter="35"
添加一个新的哈希表,就像我对“BIB2”所做的那样,但我收到了错误:
在此对象上找不到属性“Bücher”。验证该属性 存在并且可以设置。 在行:5 字符:1 + $data.BIBs.BIB1.Bücher += @Motor="asdf";pers="345" + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException +fullyQualifiedErrorId:PropertyAssignmentException你知道我如何将@Person="Max";Alter="35"
添加到“Bücher”吗?
【问题讨论】:
分配不明确 - 是否应该写信给$Data.BIBs[0].BIB1[0].Bücher
?那肯定不存在
$data.BIBs.GetType()
和 $data.BIBs.BIB1.GetType()
的结果是什么?
两者的结果同上:System.Array
阅读和写作不是一回事。您在阅读时依赖于属性枚举
好的,这意味着我不能像我想要的那样将我的哈希表写入“Bücher”?我该怎么做呢?为什么可以写例如“BIB2”到“BIBs”,我也依赖一个属性,还是只是依赖多个属性的问题?
【参考方案1】:
tl;dr
不支持通过成员枚举设置键/属性值(见下文)。
相反,您必须获取要显式修改其.Bücher
属性的特定对象:
($Data.BIBs.BIB1 | ? Bücher).Bücher += @ BuchName='neues Buch'; Autor='Johann Doe'
注意:这假设:
数组$Data.BIBs.BIB1
中只有一个 元素具有.Bücher
属性(键)
如果属性/键确实存在,它是非空,因此在布尔上下文中是“真实的”,例如传递给?
(Where-Object
) 的表达式;与成员枚举类似,这种简化的 Where-Object
语法 - ? Bücher
而不是 ? $_.Bücher
- 是一种称为 比较语句 的 PSv3+ 功能。
Mathias R. Jessen 在 cmets 中提供了关于该问题的关键指针:
PowerShell 在 getting 值与 setting 值的 collection-valued 属性之间有意不对称。
在 getting 时,PSv3+ 应用 member enumeration,简而言之,它允许您访问 collection 上的属性并隐式地访问从该集合中的每个元素获取该属性的值,并将结果收集到一个数组中。
在设置中,不应用成员枚举;理由是无意修改数据的风险太高 - 请参阅 PS 团队核心成员的 GitHub issue #5271,尤其是 this comment。
不幸的是,当前的错误消息并没有告诉你。 它源于这样一个事实:当尝试在集合级别设置属性时,仅直接在集合上查找该属性(而不是在其元素上),其中它(通常)不存在。
我们来看一个简化的例子:
$data = @ # a hashtable
a = ( # array of hashtables
@ b1 = 'b1' ,
@ b2 = 'b2' ,
@ b3 =
@ b31 = 'b31' , @ b32 = 'b32' # array of hashtables
)
在获取时,一切工作正常:
PS> $data.a.b3
Name Value
---- -----
b31 b31
b32 b32
尽管$data.a
是一个[object[]]
数组,但在其元素 中发现了一个具有.b3
属性的对象(哈希表),并输出了该对象的.b3
值。
这是实际中的成员枚举(尽管更典型的用途是属性存在于数组的所有元素上,以及将单个值收集在[object[]]
数组中)。
在设置上,PowerShell 放弃了成员枚举,因此未成功地在@987654342 上仅直接查找.b3
属性@ 实例是 $data.a
,当然,数组没有 .b3
属性:
PS> $data.a.b3 += @ b33 = 'b33' # Try to add an element; !! FAILS
The property 'b3' cannot be found on this object.
Verify that the property exists and can be set.
...
【讨论】:
以上是关于如何将哈希表添加到多维数组?无法通过成员枚举赋值的主要内容,如果未能解决你的问题,请参考以下文章