如何将哈希表添加到多维数组?不能通过成员枚举赋值 [英] How to add hashtable to multidimensional array? Cannot assign values via member enumeration

查看:31
本文介绍了如何将哈希表添加到多维数组?不能通过成员枚举赋值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在将哈希表添加到多维数组时遇到问题.我编写了以下代码:

$Data = @{BIBs = @(@{$BIB = @{BIBName=$BIBName},@{Standort = $Standort},@{Bücher = @(@{BuchName = $BuchName;Autor = $Autor})}})}

此代码正在运行并创建一个输出,我将其存储在 JSON 中:

{BIB":[{BIB1":[{"BIBName": "123"},{标准":123"},{Bücher":[{"作者": "123",书名":123"}]}]},{BIB2":[{"BIBname": "345"},{标准":345"},{Bücher":[{"作者": "345",书名":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+ FullQualifiedErrorId:PropertyAssignmentException

你知道我是如何将 @{Person="Max";Alter="35"} 添加到Bücher"的吗?

解决方案

tl;dr

不支持通过成员枚举

设置键/属性值(见下文).

相反,您必须获取要显式修改其 .Bücher 属性的特定对象:

($Data.BIBs.BIB1 | ? Bücher).Bücher += @{ BuchName='neues Buch';Autor='约翰·多伊' }

注意:这里假设:

  • 只有一个数组$Data.BIBs.BIB1有一个.Bücher属性(键)
  • 也就是说,如果属性/键确实存在,它是非空,因此是真实的";在布尔上下文中,例如传递给 ? (Where-Object) 的表达式;像成员枚举一样,这种简化的 Where-Object 语法 - ?Bücher 而不是 ?{ $_.Bücher } - 是一种称为比较语句的 PSv3+ 功能.

Mathias R. Jessen 在对该问题的评论中提供了关键的指针:

PowerShell 在集合值 属性的点符号方面有意不对称,用于获取 值与设置 值.

  • 获取时,PSv3+ 应用成员枚举,简而言之,它允许您访问 集合 上的属性,并从 该集合中的每个元素 隐式获取该属性的值,并将结果收集到一个数组.

  • 设置时,应用成员枚举;理由是无意修改数据的风险太高 - 请参阅 GitHub 问题 #5271 尤其是 PS 核心成员的此评论团队.

不幸的是当前的错误消息没有告诉你.
它源于这样一个事实:当尝试在集合级别设置一个属性时,该属性仅直接在集合上(而不是在其元素上)被查找,其中它(通常)不存在.

我们来看一个简化的例子:

$data = @{ # 一个哈希表a = ( # 哈希表数组@{ b1 = 'b1' },@{ b2 = 'b2' },@{ b3 =@{ b31 = 'b31' }, @{ b32 = 'b32' } # 哈希表数组})}

获取后,一切工作正常:

PS>$data.a.b3名称值---- -----b31 b31b32 b32

即使 $data.a 是一个 [object[]] 数组,也找到了一个具有 .b3 属性的对象(哈希表)在它的元素中,输出那个对象的.b3值.
这是实际中的成员枚举(尽管更典型的用途是属性存在于数组的所有 元素上,以及要在 [object[]] 中收集各个值的情况 数组).

设置时,PowerShell 放弃成员枚举,因此仅查找.b3 属性失败 直接在 [object[]] 实例上,即 $data.a,当然,数组没有 .b3 属性:

PS>$data.a.b3 += @{ b33 = 'b33' } # 尝试添加一个元素;!!失败在此对象上找不到属性b3".验证该属性是否存在并且可以设置....

I'm having trouble with adding hashtables to a multidimensional array. I coded the following:

$Data = @{BIBs = @(
    @{$BIB = @{BIBName=$BIBName}, 
    @{Standort = $Standort}, 
    @{Bücher = @(
        @{BuchName = $BuchName; 
        Autor = $Autor
        })
    }}
)}

This code is functioning and creates an output, which I store in a JSON:

{
    "BIBs": [
        {
            "BIB1": [
                {
                    "BIBName": "123"
                },
                {
                    "Standort": "123"
                },
                {
                    "Bücher": [
                        {
                            "Autor": "123",
                            "BuchName": "123"
                        }
                    ]
                }
            ]
        },
        {
            "BIB2": [
                {
                    "BIBname": "345"
                },
                {
                    "Standort": "345"
                },
                {
                    "Bücher": [
                        {
                            "Autor": "345",
                            "Buchname": "345"
                        }
                    ]
                }
            ]
        }
    ]
}

I have extra code which adds another hashtable to array "BIBs" as you can see.

$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})}
}

When the output is like above, I'm not able to add another hashtable to "Bücher". I checked the type of "Bücher" with

$data.BIBs.BIB1.Bücher.GetType()

and it's actually an array:

IsPublic IsSerial Name     BaseType
-------- -------- ----     --------
True     True     Object[] System.Array

I tried

$Data.BIBs.BIB1.Bücher += @{Person="Max";Alter="35"}

to add a new hashtable, like I did with "BIB2", but I am getting the error:

The property 'Bücher' cannot be found on this object. Verify that the property
exists and can be set.
At line:5 char:1
+ $data.BIBs.BIB1.Bücher += @{Motor="asdf";pers="345"}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyAssignmentException

Do you know how I add @{Person="Max";Alter="35"} to "Bücher"?

解决方案

tl;dr

Setting a key / property value via member enumeration is not supported (see below).

Instead, you must obtain the specific object whose .Bücher property you want to modify explicitly:

($Data.BIBs.BIB1 | ? Bücher).Bücher += @{ BuchName='neues Buch'; Autor='Johann Doe' }

Note: This assumes that:

  • only one element of array $Data.BIBs.BIB1 has a .Bücher property (key)
  • that, if the property / key does exist, it is nonempty and therefore is "truthy" in a Boolean context, such as the expression passed to ? (Where-Object); like member enumeration, this simplified Where-Object syntax - ? Bücher instead of ? { $_.Bücher } - is a PSv3+ feature called comparison statement.

Mathias R. Jessen has provided the crucial pointer in comments on the question:

PowerShell has an intentional asymmetry with respect to dot notation across collection-valued properties for getting values vs. setting values.

  • On getting, PSv3+ applies member enumeration, which, in a nutshell, allows you to access a property on a collection and implicitly get that property's value from each element IN that collection, with the results getting collected in an array.

  • On setting, member enumeration is not applied; the rationale is that the risk of unintentional modification of data is too high - see GitHub issue #5271 and in particular this comment by a core member of the PS team.

The unfortunate aspect is that the current error message doesn't tell you that.
It stems from the fact that when attempting to set a property at the collection level, the property is looked for only directly on the collection (instead of on its elements), where it (usually) doesn't exist.

Let's take a look at a simplified example:

$data = @{ # a hashtable
  a = ( # array of hashtables
    @{ b1 = 'b1' },
    @{ b2 = 'b2' },
    @{ b3 = 
      @{ b31 = 'b31' }, @{ b32 = 'b32' } # array of hashtables
    }
  )
}

On getting, everything works fine:

PS> $data.a.b3

Name                           Value                                                                                                                                                                                                                            
----                           -----                                                                                                                                                                                                                            
b31                            b31                                                                                                                                                                                                                              
b32                            b32                                                                                                                                                                                                                              

Even though $data.a is an [object[]] array, an object (hashtable) with property .b3 was found among its elements, and that object's .b3 value is output.
This is member enumeration in action (although the more typical uses is case for the property to exist on all elements of the array and for the individual values to be collected in an [object[]] array).

On setting, PowerShell forgoes member enumeration and therefore unsuccessfully looks for a .b3 property only directly on the [object[]] instance that is $data.a and, of course, arrays have no .b3 property:

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

这篇关于如何将哈希表添加到多维数组?不能通过成员枚举赋值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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