如何将哈希表添加到多维数组?无法通过成员枚举赋值

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.
...

【讨论】:

以上是关于如何将哈希表添加到多维数组?无法通过成员枚举赋值的主要内容,如果未能解决你的问题,请参考以下文章

在表视图内的集合视图中传递多维数组

如何将多维数组添加到序列化的 POST 数据中?

在 Powershell 中创建多维哈希表数组

如何通过表行而不是php中的列来回显多维数组值[关闭]

哈希表

通过 PHP cURL 将多维数组发布到 PayPal