programing

개체에 특정 속성이 있는지 어떻게 테스트할 수 있습니까?

sourcejob 2023. 4. 29. 09:15
반응형

개체에 특정 속성이 있는지 어떻게 테스트할 수 있습니까?

개체에 특정 속성이 있는지 어떻게 테스트할 수 있습니까?

할 수 있어서 감사합니다...

$members = Get-Member -InputObject $myobject 

그리고 나서.foreach을 통하여$members하지만 물체가 특정한 특성을 가지고 있는지 테스트할 수 있는 기능이 있습니까?

추가 정보:문제는 두 가지 종류의 CSV 파일을 가져온다는 것입니다. 하나는 열이 두 개이고 다른 하나는 열이 세 개입니다."속성"에 대한 검사를 받을 수 없습니다. "속성"에만 해당됩니다. 차이점이 무엇이든 간에

if ( ($member.MemberType -eq "NoteProperty" ) -and ($member.Name -eq $propertyName) ) 

이렇게요?

 [bool]($myObject.PSobject.Properties.name -match "myPropertyNameToTest")

사용할 수 있습니다.Get-Member

if (Get-Member -inputobject $var -name "Property" -Membertype Properties) {
    #Property exists
}

이것은 간결하고 읽기 쉬운 것입니다.

"MyProperty" -in $MyObject.PSobject.Properties.Name

함수에 넣을 수 있습니다.

function HasProperty($object, $propertyName)
{
    $propertyName -in $object.PSobject.Properties.Name
}

나를 위해.MyProperty" -in $MyObject.PSobject.Properties.Name하지만 효과가 없었습니다.

$MyObject.PSobject.Properties.Name.Contains("MyProperty")

작동하다

엄격한 모드에서 작동하는 이 질문에 대한 많은 해결책이 있지만 일부는 다른 해결책보다 더 낫습니다.

모든 속성을 통해 반복되지 않는 솔루션이 가장 빠른 솔루션입니다.

  1. 버니 화이트의 해결책과
  2. 에스카르 용액(수정)

모든 속성을 반복하는 것처럼 보이는 솔루션은 더 느립니다.

  1. 세베크 CCU의 솔루션과
  2. 당그프 용액

모든 속성을 반복하고 정규식을 사용하는 것으로 나타나는 솔루션은 이전 두 솔루션보다 약간 느립니다(정규식을 컴파일하고 실행하는 데 더 많은 시간이 걸리기 때문).

  1. CB의 해결책

GetMethod를 사용하는 솔루션은 모든 속성을 통해 반복되는 것으로 보이지만 사용하는 것은GetMethod속도가 상당히 느려집니다.

  1. Paul's GetMethod 솔루션

다음 스크립트는 이전에 언급한 솔루션을 엄격한 모드로 비교하는 데 사용되었습니다.

# Tested in PowerShell core 7.2.0

Set-StrictMode -Version Latest

$propertyExistsMethods = New-Object System.Collections.Generic.Dictionary'[string,scriptblock]'

# Fastest
$propertyExistsMethods.Add(
 "PSObject.Properties (Bernie White's solution)",
{
  Param( [PSObject] $Object, [string] $Property )
  [bool]$Object.PSObject.Properties[$Property]
})
$propertyExistsMethods.Add(
 "PSObject.Properties.Item (esskar's solution (modified))",
{
  Param( [PSObject] $Object, [string] $Property )
  [bool]$Object.PSObject.Properties.Item($property)
})

# Not as fast
$propertyExistsMethods.Add(
 "Contains (sebke CCU's solution)",
{
  Param( [PSObject] $Object, [string] $Property )
  $Object.PSobject.Properties.Name.Contains($Property)
})
$propertyExistsMethods.Add(
 "-in (dan-gph's solution)",
{
  Param( [PSObject] $Object, [string] $Property )
  $Property -in $Object.PSobject.Properties.Name
})

# Slower than the previously mentioned solutions
$propertyExistsMethods.Add(
 "-match (CB.'s solution)",
{
  Param( [PSObject] $Object, [string] $Property )
  [bool]($Object.PSobject.Properties.name -match $Property)
})

# Slowest
$propertyExistsMethods.Add(
 "GetMember (Paul's solution)",
{
  Param( [PSObject] $Object, [string] $Property )
  Get-Member -inputobject $Object -name $Property -Membertype Properties
})

foreach ($method in $propertyExistsMethods.Keys) {
  $propertyExists = $propertyExistsMethods[$method]

  $o = @{}
  foreach ($i in 1..100000) {
    $o[$i] = "p$i"
  }

  Write-Host $method
  $measure = Measure-Command {
    foreach ($i in 1..100000) {
      # Always check for a property that does NOT exist
      & $propertyExists -Object $o -Property 'p'
    }
  }
  Write-Host $measure | % { $_.Milliseconds }
  Write-Host ''
}

출력은 다음과 같습니다.

PSObject.Properties (Bernie White's solution)
00:00:03.1437587

PSObject.Properties.Item (esskar's solution)
00:00:03.5833642

Contains (sebke CCU's solution)
00:00:04.4812702

-in (dan-gph's solution)
00:00:04.6507811

-match (CB.'s solution)
00:00:05.1107066

GetMember (Paul's solution)
00:00:14.5305115

안전성이 엄격한 라이너 하나를 위해 이것을 사용해 보세요.

[bool]$myobject.PSObject.Properties[$propertyName]

예:

Set-StrictMode -Version latest;
$propertyName = 'Property1';
$myobject = [PSCustomObject]@{ Property0 = 'Value0' };

if ([bool]$myobject.PSObject.Properties[$propertyName]) {
    $value = $myobject.$propertyName;
}

저는 "속성"이 존재하고 임의의 예외를 던지지 않는 경우 를 통해 액세스할 있는 속성 값을 반환하는 다음을 사용해 왔습니다.속성이 "존재하지 않음"(또는 null 값)이면$null반환됩니다. 이 접근 방식은 엄격한 모드에서 작동합니다. 왜냐하면, 모든 것을 잡을 수 있기 때문입니다.

저는 이 접근 방식이 PS 사용자 정의 개체를 일반적으로 허용하기 때문에 유용하다고 생각합니다.NET 개체, PS 해시 테이블 및 .Dictionary와 같은 NET 컬렉션은 "오리형 등가물"로 취급되며 PowerShell에 상당히 적합합니다.

물론, 이것은 "재산을 가지고 있다"라는 엄격한 정의를 충족하지 못합니다.이 질문은 명시적으로 제한될 수 있습니다.여기서 가정한 "속성"의 더 큰 정의를 수락하면 부울을 반환하도록 메소드를 약간 수정할 수 있습니다.

Function Get-PropOrNull {
    param($thing, [string]$prop)
    Try {
        $thing.$prop
    } Catch {
    }
}

예:

Get-PropOrNull (Get-Date) "Date"                   # => Monday, February 05, 2018 12:00:00 AM
Get-PropOrNull (Get-Date) "flub"                   # => $null
Get-PropOrNull (@{x="HashTable"}) "x"              # => "HashTable"
Get-PropOrNull ([PSCustomObject]@{x="Custom"}) "x" # => "Custom"
$oldDict = New-Object "System.Collections.HashTable"
$oldDict["x"] = "OldDict"
Get-PropOrNull $d "x"                              # => "OldDict"

그리고 이 동작은 [항상] 바람직하지 않을 수 있습니다.i. 사이를 구별하는 것은 가능하지 않습니다.x.Count그리고.x["Count"].

null을 확인하십시오.

($myObject.MyProperty -ne $null)

PowerShell을 StrictMode로 설정하지 않은 경우 속성이 존재하지 않는 경우에도 이 기능이 작동합니다.

$obj = New-Object PSObject;                                                   
Add-Member -InputObject $obj -MemberType NoteProperty -Name Foo -Value "Bar";
$obj.Foo; # Bar                                                                  
($obj.MyProperty -ne $null);  # False, no exception

StrictMode를 사용하는 경우 psobject가 비어 있을 수 있으면 오류가 표시됩니다.

모든 목적에서 이 작업은 다음과 같습니다.

    if (($json.PSobject.Properties | Foreach {$_.Name}) -contains $variable)

Javascript 검사와 유사한 실제:

foreach($member in $members)
{
    if($member.PropertyName)
    {
        Write $member.PropertyName
    }
    else
    {
        Write "Nope!"
    }
}

여러 속성을 확인할 때 이 방법이 더 엄격하고 빠릅니다.

$null -ne $myobject.PSObject.Properties.Item("myPropertyNameToTest")

다음과 같은 목적을 고려할 때 단지 명확히 하기 위해.

$Object

다음 속성을 사용

type        : message
user        : john.doe@company.com
text        : 
ts          : 11/21/2016 8:59:30 PM

다음은 사실입니다.

$Object.text -eq $NULL
$Object.NotPresent -eq $NULL

-not $Object.text
-not $Object.NotPresent

따라서 이름으로 속성을 명시적으로 확인하는 이전 답변이 해당 속성이 없음을 확인하는 가장 올바른 방법입니다.

저는 결국 다음과 같은 기능을 갖게 되었습니다...

function HasNoteProperty(
    [object]$testObject,
    [string]$propertyName
)
{
    $members = Get-Member -InputObject $testObject 
    if ($members -ne $null -and $members.count -gt 0) 
    { 
        foreach($member in $members) 
        { 
            if ( ($member.MemberType -eq "NoteProperty" )  -and `
                 ($member.Name       -eq $propertyName) ) 
            { 
                return $true 
            } 
        } 
        return $false 
    } 
    else 
    { 
        return $false; 
    }
}

최근에 strict-mode 버전 2.0으로 전환했는데 null 테스트가 실패했습니다.

다음 기능을 추가했습니다.

#use in strict mode to validate property exists before using
function exists {
  param($obj,$prop)
  try {
    if ($null -ne $obj[$prop]) {return $true}
    return $false
  } catch {
    return $false
  }
  return $false
}

이제 코드를 작성합니다.

if (exists $run main) { ...

보다는

if ($run.main -ne $null) { ...

그리고 우리는 가는 중입니다.개체 및 해시 테이블에서 작동하는 것 같습니다.

의도하지 않은 이점으로 타이핑이 적습니다.

나에게 이 일은

Set-StrictMode -Version Latest
$TMP = ...

$HAS_SERVERS=($TMP | Select-Object Servers)
if (-not $HAS_SERVERS.Servers){
    echo "No servers. Abort."
} else {
    ...
}
 

PowerShell을 PowerShell Core 6.0(베타)과 함께 사용하기 시작했으며 다음과 같은 간단한 작업을 수행합니다.

if ($members.NoteProperty) {
   # NoteProperty exist
}

또는

if (-not $members.NoteProperty) {
   # NoteProperty does not exist
}

다음을 통해 확인할 수 있습니다.

($Member.PropertyNames -contains "Name")합니다.

배열에 있는 개체 중 속성이 있는 개체 식별

$HasProperty = $ArrayOfObjects | Where-Object {$_.MyProperty}

언급URL : https://stackoverflow.com/questions/26997511/how-can-you-test-if-an-object-has-a-specific-property

반응형