Object Array Comparison with Custom Headers

匆匆过客 提交于 2019-12-24 15:22:57

问题


I have an object array of roles I pulled from two vcenters.

I'm trying to make a formatted table that has 3 columns : roles, master, slave

There would be "exists" or "missing" in the latter two columns.

The problem I believe happening is when it finds that the role exists in the master, it somehow marks the slave column as "missing", even though I know it's there.

I'm only a few months into Powershell, can anyone see anything wrong with my logic?

edit: RoleTable.AllRoles, RoleTable.MasterRoles, and RoleTable.SlaveRoles are all object arrays

    $RoleTable.AllRoles | Select-Object Name, 
    @{Name = "Master Server"; Expression = {if ($RoleTable.MasterRoles -contains $_) {"EXISTS"} else {"MISSING"}}}, 
    @{Name = "Slave Server"; Expression = {if ($RoleTable.SlaveRoles -contains $_) {"EXISTS"} else {"MISSING"}}}

Example of Roletable.Allroles object:

$RoleTable.AllRoles[1] | Select-Object *


Description   : Not logged-in user (cannot be granted)
IsSystem      : True
PrivilegeList : {System.Anonymous}
ServerId      : /VIServer=someuser@xxxx-xxxx:443/
Server        : 
Id            : -4
Name          : Anonymous
Uid           : /VIServer=someuser@xxxx-xxxx:Role=-4/
ExtensionData : VMware.Vim.AuthorizationRole
Client        : VMware.VimAutomation.ViCore.Impl.V1.VimClient

回答1:


Unless $RoleTable.AllRoles[1] and an item in $RoleTable.SlaveRoles refer to the exact same object in memory, -contains will return $false, even if a seemingly identical object exists in $RoleTable.SlaveRoles.

(this is only true for reference types, not value types)

This should illustrate the difference:

Reference to same object:

PS C:\> $Collection = @(New-Object psobject -Property @{p=123})
PS C:\> $Item       = $Collection[0]
PS C:\> $Collection -contains $Item 
True 

Reference to identical object:

PS C:\> $Collection = @(New-Object psobject -Property @{p=123})
PS C:\> $Item       = New-Object psobject -Property @{p=123}
PS C:\> $Collection -contains $Item 
False

In your example, you could use the Name or role Id property (as suggested by @jisaak):

$RoleTable.AllRoles | Select-Object Name, 
@{Name = "OnMaster"; Expression = {$RoleTable.MasterRoles.Id -contains $_.Id}}, 
@{Name = "OnSlave"; Expression = {$RoleTable.SlaveRoles.Id -contains $_.Id}}

As shown above, I would probably use generic boolean values as indicators, rather than strings


This behaviour is a deliberate performance optimization in .NET - you never know how deep down the rabbit hole you would need to go to ensure exact value comparison of all internal attributes of an object.

Value types, on the other hand, are easier to perform equality comparisons against (and also don't necessarily have a memory reference to compare), resulting in:

[int]

PS C:\> $Collection = @(283)
PS C:\> $Item       = $Collection[0]
PS C:\> $Collection -contains $Item
True
PS C:\> $Item       = 283
PS C:\> $Collection -contains $Item
True

[string]:

PS C:\> $Collection = @("SomeString")
PS C:\> $Item       = $Collection[0]
PS C:\> $Collection -contains $Item
True
PS C:\> $Item       = "SomeString"
PS C:\> $Collection -contains $Item
True

and so on...



来源:https://stackoverflow.com/questions/31857138/object-array-comparison-with-custom-headers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!