none
How can I match these 3 conditions - If-And

    Question

  • I'm looping through an array and trying to match these 3 conditions:

    C1 - $item.LastRunDate -ne "Never"

    C2 - ($DATE - $item.LastRunDate).TotalDays -lt 31

    C3 - $item.OwnerLoginName -eq ""

    The first condition needs to be met first, otherwise the second condition breaks  (date/math operation on string). 

    I tried: If ((C1) -and (C2 -and C3)) {do this}

    and multiple variations, but no success.  Please advise; thanks.




    Wednesday, June 20, 2012 5:59 PM

Answers

  • # use the Is operator to check if the type of LastRunDate is DateTime
    if ($item.LastRunDate -is [DateTime] -and ($DATE - $item.LastRunDate).TotalDays -lt 31 -and $item.OwnerLoginName -eq "") {do this}

    # you can also negate the value in last comparison, if it is empty, negating it returns True
    if ($item.LastRunDate -is [DateTime] -and ($DATE - $item.LastRunDate).TotalDays -lt 31 -and -not $item.OwnerLoginName) {do this}


    Many scripters feel more comfortable by wrapping the comparisons in parentheses, they claim it improves readability. I disagree; I only wrap comparisons when necessary ;)

    Also, if the line gets too long, you can break the line after each And operator.



    • Edited by zx38 Wednesday, June 20, 2012 6:52 PM Typo
    • Marked as answer by tickermcse76 Thursday, June 21, 2012 1:20 AM
    Wednesday, June 20, 2012 6:49 PM

All replies

  • # use the Is operator to check if the type of LastRunDate is DateTime
    if ($item.LastRunDate -is [DateTime] -and ($DATE - $item.LastRunDate).TotalDays -lt 31 -and $item.OwnerLoginName -eq "") {do this}

    # you can also negate the value in last comparison, if it is empty, negating it returns True
    if ($item.LastRunDate -is [DateTime] -and ($DATE - $item.LastRunDate).TotalDays -lt 31 -and -not $item.OwnerLoginName) {do this}


    Many scripters feel more comfortable by wrapping the comparisons in parentheses, they claim it improves readability. I disagree; I only wrap comparisons when necessary ;)

    Also, if the line gets too long, you can break the line after each And operator.



    • Edited by zx38 Wednesday, June 20, 2012 6:52 PM Typo
    • Marked as answer by tickermcse76 Thursday, June 21, 2012 1:20 AM
    Wednesday, June 20, 2012 6:49 PM
  • I tried your suggestions but they did not return the results I expected.

    Of the 3 conditions, I can always include any 2 and the results will match the criteria of those 2 conditions (I can see both the items I want to match and the ones I want to exclude).  It is only an issue when I introduce the 3rd condtion that the desired results are not returned (I always get no matches). 

    The reason for all the parentheses in my example is I followed the information in this link: http://itnotes.net/2011/02/25/powershell-multiple-and-or-within-a-single-if-statement/.


    Wednesday, June 20, 2012 7:16 PM
  • Hi wallst360, I was not criticizing you for the parentheses, I was given you a reason why I did not use them. In the article they have a mixed comparison, that is they first use the Or operator to join two conditional statements which are evaluated first, then that result is joined with the And operator to another conditional statement. As I said, sometimes it is necessary to use parentheses.

    When you have conditional statements joined with the And operator, all must return True for the joined conditional to return True. For instance, in your code, if the 1st test is not successful, the following tests are not evaluated and the if statement block is not executed. If the 1st test is successful but the 2nd test is not, the 3rd test is not evaluated and the if statement block is not executed. If the 1st and 2nd tests are successful but the 3rd test is not, the if statement block is not executed. All of these tests must be successful — return True — for the entire comparison statement to return True — successful, then the if statement block is executed. Run these lines one at a time to see:

    $false -and $true -and $true
    $true -and $false -and $true
    $true -and $true -and $false
    $true -and $true -and $true

    I setup a test and the comparison works, that is, if all tests return true, do something. My test just filters the item when all three conditions are successful. This is the code I ran, it creates records that contain fields with values similar to yours and stores them in the variable data. Next, it tests the value of LastRunDate is of type DateTime (1st test), the difference — in days —between the value of the variable date (in this case is today) and the value of LastRunDate is less than thirty-one (2nd test) and the value of OwnerLoginName is empty (3rd test). If all tests are successful, the statement block is executed, outputting the item. The matching items are stored in the variable data2.

    $data = foreach ($i in 1..30) {
      New-Object PSObject -Property @{
        Number = $i
        ID = '{0}{1:00}' -f (-join ([Char[]](65..90) | Get-Random -Count 5)), $i
        LastRunDate = if (-not ($i % 5) -or -not ($i % 11)) {
          [DateTime]::Today.AddDays(-(Get-Random -Minimum 7 -Maximum 30))
        } elseif (-not ($i % 6)) {
          'Never'
        } else {
          [DateTime]::Today.AddDays(-(Get-Random -Minimum 31 -Maximum 90))
        }
        OwnerLoginName = if (-not ($i % 7) -or -not ($i % 11)) {
          ''
        } else {
          'User{0:00}' -f $i
        }
      }
    }
    $date = [DateTime]::Today
    $data2 = foreach ($item in $data) {
      if ($item.LastRunDate -is [DateTime] -and
            ($date - $item.LastRunDate).TotalDays -lt 31 -and
                $item.OwnerLoginName -eq '') {
        $item
      }
    }
    Clear-Host
    Write-Host Filtered -BackgroundColor Yellow -ForegroundColor DarkBlue
    $data2 | Out-Default
    Write-Host Unfiltered -BackgroundColor Blue -ForegroundColor White
    $data

    Here is the output. I have highlighted the comparison results.

    • Orange = 1st test is successful
    • Cyan = 1st and 2nd test are successful
    • Purple = 3rd test would have been successful but it was never evaluated
    • Green = All tests are successful



    • Edited by zx38 Thursday, June 21, 2012 1:07 AM
    • Proposed as answer by King Julien Thursday, June 21, 2012 6:32 AM
    Thursday, June 21, 2012 12:04 AM
  • I got it working now.  I had filtered down the array contents for testing purposes as the entire data set takes awhile to process.  What I thought covered all my scenarios in fact did not. 

    Thanks for your responses zx38.  They confirmed I should look elsewhere for an error and I certainly learned a new technique or two.

    Thursday, June 21, 2012 1:32 AM
  • Excellent!

    You're welcome. I'm glad to help.


    • Edited by zx38 Thursday, June 21, 2012 2:01 AM
    Thursday, June 21, 2012 2:00 AM