if Statement with multiple options

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • wyzbs
    New Member
    • Oct 2010
    • 3

    #1

    if Statement with multiple options

    Hi,

    I'm wondering is there a way to shorten this IF statement:

    Code:
     if (a == b || a == c || a == d)
    {
    code
    }
    to
    Code:
     if (a == (b or c or d) )
    {
    code
    }

    Thank you
  • Curtis Rutland
    Recognized Expert Specialist
    • Apr 2008
    • 3264

    #2
    No, there is not.

    Comment

    • wyzbs
      New Member
      • Oct 2010
      • 3

      #3
      OK. Thanks a lot

      Comment

      • GaryTexmo
        Recognized Expert Top Contributor
        • Jul 2009
        • 1501

        #4
        <digress>
        You know, I'm surprised a language hasn't developed something like this. I remember, oh so many years ago, when I first started programming in QBasic I tried to do that exact same thing. My first if statement was something along the lines of...

        Code:
        IF age = 18 OR 25 THEN
        ... which is obviously ambiguous, but with the use of brackets the OP's shortened version is clear. Of course, now I'm too used to the current way of doing it, but I do find it noteworthy that new programmers often make that mistake.
        </digress>

        Comment

        • Curtis Rutland
          Recognized Expert Specialist
          • Apr 2008
          • 3264

          #5
          You know, I've thought about this. You could do something like this, but it's clunky:

          Code:
          int age = 24;
          if ((new int[] { 18, 25 }).Contains(age))
              Console.WriteLine("yes");
          else
              Console.WriteLine("no");
          Hardly faster than the other way. But if you had four or five values, it might be better.

          I've come up with a static class that makes creating these sequences a bit easier:

          Code:
          public static class Seq
          {
              public static IEnumerable<int> Make(int min, int max)
              {
                  for (int i = min; i <= max; i++)
                      yield return i;
              }
          
              public static IEnumerable<int> Make(Func<int, int> iterator, int min, int max)
              {
                  do
                  {
                      yield return min;
                      min = iterator.Invoke(min);
                  } while (min <= max);
              }
          
              public static IEnumerable<T> Make<T>(params T[] list)
              {
                  foreach (T item in list)
                      yield return item;
              }
          }
          I got the idea from F#'s seq method.

          You can easily create a continuous list of ints:
          Seq.Make(1, 10)
          {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
          Or one that has an iterator method:
          Seq.Make(x => x += 2, 1, 10)
          {1, 3, 5, 7, 9}
          Or even one with just the values you want:
          Seq.Make<int>(1 , 2, 4)
          {1, 2, 4}
          I made that last one generic because it's easy to. The other ones require a numeric type. Generic type constraints are possible, but there is no constraint that says "numeric." So, you could implement the extra methods using doubles/whatever if you wanted to.

          I actually like the one that uses a function as a parameter. You can do stuff like this:
          Code:
          Seq.Make(x => x % 2 == 0 ? x + 3 : x + 5, 1, 50)
          1, 6, 9, 14, 17, 22, 25, 30, 33, 38, 41, 46, 49
          Or even go so far as to do this:
          Code:
          private static int DoSomething(int x)
          {
              //do lots of stuff to x
              return x + 1;
          }
          ...
          ...
          Seq.Make(DoSomething, 1, 10)

          Anyway. To your example, you could do something like this:
          Code:
          if (Seq.Make<int>(18, 25).Contains(age))
              Console.WriteLine("yes");
          else
              Console.WriteLine("no");
          So, I went off on a tangent of my own, but am having fun.

          Comment

          • Curtis Rutland
            Recognized Expert Specialist
            • Apr 2008
            • 3264

            #6
            Oh, I came up with some useful extension methods to go along:

            Code:
            public static class Extensions
            {
                public static bool In(this int i, IEnumerable<int> collection)
                {
                    return collection.Contains(i);
                }
            
                public static void Print<T>(this IEnumerable<T> collection, TextWriter writer = null)
                {
                    if (writer == null)
                        writer = Console.Out;
                    StringBuilder sb = new StringBuilder("{");
                    foreach (T item in collection)
                        sb.Append(string.Format("{0}, ", item));
                    sb.Append("}");
                    sb.Remove(sb.Length - 3, 2);
                    Console.WriteLine(sb.ToString());
                }
            }
            So, you can do things like:
            Code:
            if(age.In(Seq.Make(18, 25)))
                Console.WriteLine("yes");
            else
                Console.WriteLine("no");
            Or even 25.In(Seq.Make( 18, 25))

            Also, the Print method will conveniently print a collection using the provided TextWriter or Console.Out.

            Comment

            • GaryTexmo
              Recognized Expert Top Contributor
              • Jul 2009
              • 1501

              #7
              You know, that's the thing about programmers. We'll happily spend more time avoiding a "problem" than just doing the "workaround " ;)

              In the spirit of fun, it occurred to me that you could quite easily create a comparer class to do all sorts of comparisons for you.

              Code:
                  class Program
                  {
                      static void Main(string[] args)
                      {
                          if (Comparer<int>.Compare(Comparer<int>.CompareType.Or, 11, new int[] { 18, 25 }))
                          {
                              Console.WriteLine("Pass");
                          }
                          else
                          {
                              Console.WriteLine("Fail");
                          }
              
                          if (Comparer<string>.Compare(Comparer<string>.CompareType.And, "Gary", new string[] { "Gary", "Gary" }))
                          {
                              Console.WriteLine("Pass");
                          }
                          else
                          {
                              Console.WriteLine("Fail");
                          }
                      }
                  }
              
                  public static class Comparer<T> where T : IComparable
                  {
                      public enum CompareType
                      {
                          Or,
                          And
                      }
              
                      public static bool Compare(CompareType compareType, T value, T[] items)
                      {
                          bool ret = true;
                          foreach (T obj in items)
                          {
                              if (value.CompareTo(obj) != 0)
                              {
                                  ret = false;
                                  if (compareType == CompareType.And) break;
                              }
                              else
                              {
                                  ret = true;
                              }
                          }
              
                          return ret;
                      }
                  }
              I'm willing to bet you could put some LINQ in there as well, but I didn't 'cause I'm not familiar with it. Good ol' foreach for me ;)

              If you really wanted to get crazy, you could use a KeyValuePair for your comparisons and include greater than, less than, etc... tests for each value.

              Comment

              • GaryTexmo
                Recognized Expert Top Contributor
                • Jul 2009
                • 1501

                #8
                Hmm also, I can't seem to use your code. Do I need a different version of .NET or VS? I may be out of date... using 2008 and I should have .NET 4.x (w/e it's at) via windows update.

                Comment

                • Sigo

                  #9
                  Good job Curtis, for people that do not need the use of Sequences I've derived a simpler extension method from curtis code to allow people to do that kind of stuff:

                  Code:
                  if( 1.In(1,2,3,4) )....;
                  if( 3.123.In(3.1,3.2,3.4) )....;
                  if( "Hello".In("Hello", "World") )....;
                  
                  if (age.In(18, 25))
                      Console.WriteLine("yes");
                   else
                      Console.WriteLine("no");
                  etc...

                  Here it is:

                  Code:
                  public static bool In<T>(this T i, params T[] tab)
                  {
                      return tab.Contains(i);
                  }
                  Last edited by Curtis Rutland; Oct 20 '10, 12:37 AM. Reason: code tags

                  Comment

                  • Curtis Rutland
                    Recognized Expert Specialist
                    • Apr 2008
                    • 3264

                    #10
                    I like it, Sigo. You should make an account and start answering questions.

                    Comment

                    • Curtis Rutland
                      Recognized Expert Specialist
                      • Apr 2008
                      • 3264

                      #11
                      @Gary

                      I'm using VS2010, but I've tested it in 2008 as well. It requires the following namespaces:

                      Code:
                      using System;
                      using System.Collections.Generic;
                      using System.Linq;
                      using System.Text;
                      System.Text is for the StringBuilder in the Print extension method.

                      If that fails, tell me what the exception is.

                      Also, even though you have .NET 4 from Windows Update, you can't (as far as I'm aware) develop applications for it, because you need to use the .NET 4 SDK, which is not included, and apparently only supports VS2010.

                      Comment

                      • Christian Binder
                        Recognized Expert New Member
                        • Jan 2008
                        • 218

                        #12
                        It's not allowed in 3.5 to use use default-parameters like writer is in
                        void Print<T>(this IEnumerable<T> collection, TextWriter writer = null)

                        (btw. what's the tag to make this in-line-code-formatting?)

                        You could also create a Between-method like 10.Between(9, 11) == 10.In(Seq.Make( 9, 11)) == 10.In(Enumerabl e.Range(9, 3))

                        Extension methods are really a great thing.

                        Comment

                        • GaryTexmo
                          Recognized Expert Top Contributor
                          • Jul 2009
                          • 1501

                          #13
                          I have never heard of extension methods before... and yea I've got it working at work in VS 2010. I may not have the .NET 4 SDK installed at home (O.o) so I'll look into it.

                          These extension methods... they're freaking cool. They just get picked up out of nowhere? It seems you can name the static class anything and it still attaches the method to the correct type. Quite strange! I'm going to have to do some reading.

                          Also, best digression thread evar ;)

                          Comment

                          • Curtis Rutland
                            Recognized Expert Specialist
                            • Apr 2008
                            • 3264

                            #14
                            @Christian
                            The tag is [icode][/icode].

                            And I did forget to test the Print method, that's why it was failing. Default/named parameters are a C# 4.0 thing.

                            And I had forgotten about Enumerable.Rang e. I knew there was something like it, but I couldn't remember what.

                            Comment

                            • Joseph Martell
                              Recognized Expert New Member
                              • Jan 2010
                              • 198

                              #15
                              I may be a bit late to the party, but COBOL does allow you to write

                              Code:
                              if (a = b or c or d)...

                              Comment

                              Working...