Alternative to multiple -OR conditions in an IF-THEN-ELSE statement

Welcome Forums General PowerShell Q&A Alternative to multiple -OR conditions in an IF-THEN-ELSE statement

This topic contains 11 replies, has 6 voices, and was last updated by

 
Participant
1 week, 2 days ago.

  • Author
    Posts
  • #134270

    Participant
    Points: 235
    Rank: Participant

    I have a [simplified] CSV file with 3 properties.  Sample (subset of real data):

    Person,Amount,Category
    Joe,5,Coffee
    Mary,15,Gas
    John,25,Food
    John,10,Beer
    Mary,8,Juice
    

     

    PS code to process the above CSV is:
    
    
    $data = Import-CSV
    $data | Foreach-object -Process {
    [pscustomobject]@{Amount=$_.Amount; Person=$_.Person;
         Category=If((($_.Category).Contains('coffee') -EQ $True) -OR
             (($_.Category).Contains('tea')- EQ $True) -OR
             (($_.Category).Contains('soda') EQ $True) -OR
             (($_.Category).Contains('beer') -EQ $True) -OR
             (($_.Category).Contains('juice') -EQ $True) -EQ $True) {
                      'drink-'+$_.Category} else {$_.Category}
    }
    While it works fine, I am wondering if the five (5) -OR statements for testing the condition is the "Powershell way" of doing it.  I was considering the use of a hash table, but started with this as a first step.
    Would be grateful for any guidance, tips or advice.
    Much thanks,
  • #134273

    Participant
    Points: 235
    Rank: Participant

    Sorry, please ignore this [2nd] post (but not the original post above).

    Not intended to be a reply to the above but as a separate post.

     

  • #134289

    Participant
    Points: 132
    Helping Hand
    Rank: Participant

    I recommend you work on formatting your code in a more readable format.
    Also identify and note the 4 different syntax errors in the code above.
    The -in operator would replace multiple -eq operators in this case as in:

    # $data = Import-Csv .\filename.ext
    
    #region
    $data = @()
    $data += [PSCustomObject]@{
        Person   = 'Joe'
        Amount   = 5
        Category = 'Coffee'
    }
    $data += [PSCustomObject]@{
        Person   = 'Mary'
        Amount   = 15
        Category = 'Gas'
    }
    $data += [PSCustomObject]@{
        Person   = 'John'
        Amount   = 25
        Category = 'Food'
    }
    $data += [PSCustomObject]@{
        Person   = 'John'
        Amount   = 10
        Category = 'Beer'
    }
    $data += [PSCustomObject]@{
        Person   = 'Mary'
        Amount   = 8
        Category = 'Juice'
    }
    #endregion
    
    $CategoryList = $data.Category # or $CategoryList = @('Coffee','Cheese')
    $data | Foreach-object -Process {
        [pscustomobject]@{
            Person   = $_.Person
            Amount   = $_.Amount
            Category = $( If ($_.Category -in $CategoryList ) { 'drink-'+$_.Category } else { $_.Category } )
        }
    }
    
    • #134294

      Participant
      Points: 235
      Rank: Participant

      Many thanks Mr Boutros.  The code shown was the result of a Copy-Paste directly from VSCode editor, which in its original form was neatly formatted.  I don't understand why this led to the left-justified result and the syntax error (the blank character in VSCode, it seems, shows as a centered dot.). My apologies for this.  Secondly, I gave the sample data of just 5 lines to illustrate the nature of my question.  But I still haven't found a way to type line by line sample data without the extra space. In fact I just posted a question for this in the feedback forum.  The main purpose of the code I submitted was to convert the values of all the 5 categories of property Category (as it originated from the source) from:  (coffee,tea,soda,juice,beer) to (drink-coffee,drink-tea,drink-soda,drink-juice,drink-beer).

      Thanks again for your reply.

  • #134301

    Participant
    Points: 1,124
    Helping Hand
    Rank: Community Hero

    Within the help of calculated property and regex.

    $Category = @{
        E = {
            if($_.Category -match "tea|soda|beer|juice"){
                "Drink " + $_.Category
            }
            else{
                $_.Category
            }
        }
        L = 'Category'
    }
    $data = Import-Csv | Select-Object -Property Amount,Person,$Category
    
    • #134330

      Participant
      Points: 235
      Rank: Participant

      Mr Kvprasoon,

      Your suggestion is very neat!  I'm highly grateful for your solution.

      Much thanks.

  • #134310

    Participant
    Points: 201
    Helping Hand
    Rank: Participant

    @Ramon,

    Kvprasoon's solution is very good and I would go for that.

    However, just for information, you don't need all those -EQ True, because every expression inside the if condition is already evaluated as $true or $false.

    For example:

    PS C:\> @('blue','red').Contains('blue')
    True
    
    PS C:\> @('blue','red').Contains('black')
    False
    
    PS C:\> 
    

    Therefore, this gives the same result as your original code:

    Category=If(($_.Category).Contains('coffee') -OR
    ($_.Category).Contains('tea') -OR
    ($_.Category).Contains('soda') -OR
    ($_.Category).Contains('beer') -OR
    ($_.Category).Contains('juice')) {
    'drink-'+$_.Category}
    else {$_.Category}
    
    • #134331

      Participant
      Points: 235
      Rank: Participant

      Many thanks Mr Fullenwarth,

      Your examples are very useful and educational to me.

      Best,

  • #134322
    js

    Participant
    Points: 452
    Helping Hand
    Rank: Contributor

    I don't see how the original code can work, since .contains() is case sensitive. Anyway:

    Import-Csv food.csv | Foreach {
      [pscustomobject]@{
        Amount = $_.Amount
        Person = $_.Person
        Category = if ($_.category -in 'coffee','tea','soda','beer','juice') {
          'drink-' + $_.Category}
        else {
          $_.Category}
      }
    }
    
    
    Amount Person Category
    ------ ------ --------
    5      Joe    drink-Coffee
    15     Mary   Gas
    25     John   Food
    10     John   drink-Beer
    8      Mary   drink-Juice
    

    or:

    if ($_.category -match 'coffee|tea|soda|beer|juice') {
    

    or:

    if ('coffee','tea','soda','beer','juice' -contains $_.category) {
    

    You can actually use -eq (or -match or -like) with a list, and it will return the thing in the list from the 2nd arg and end up being true:

    PS /Users/js> 'coffee','tea','soda','beer','juice' -eq 'coffee'                  
    coffee
    PS /Users/js> 'coffee','tea','soda','beer','juice' -eq 'coffee2'                 
    PS /Users/js> 
    
    if ('coffee','tea','soda','beer','juice' -eq $_.category) {
    
  • #134339

    Participant
    Points: 201
    Helping Hand
    Rank: Participant

    Yes JS is right: the Contains method is case sentitive.
    And in addition, it must also match the whole element.

    PS C:\> @('blue','red').Contains('blue')
    True
    
    PS C:\> #Case sensitive
    @('blue','red').Contains('BLUE')
    False
    
    PS C:\> #Does not match the whole element
    @('blue','red').Contains('blu')
    
    False
    
    PS C:\> 
    
    • #134346

      Participant
      Points: 235
      Rank: Participant

      My sincerest gratitude to you all – Messrs. KVprasoon, Fullenwarth, Boutros, JS, Postanote.

      I am very thankful that besides giving me excellent answers/solutions, you have also shared many interesting aspects of Powershell and provided numerous insights.  Best,

  • #134340

    Participant
    Points: 513
    Helping Hand
    Rank: Major Contributor

    Note, VSCode, does include some random stuff that messes up copy / paste for forums and Q&A sites like this.

    So, sure format in VSCode, but copy to notepad and check before you submit / post, otherwise use GitHub, paste in, etc.. to link to your code.

    This sites', formatting code tags are what you should use when posting, and VSCode, the ISE and other tools do not do this automatically for obvious reasons. Meaning various sites, can and will have different formatting requirements.

    Create yourself the necessary shortcuts in VSCode to use the formatting tags required by the sites you post to.

You must be logged in to reply to this topic.