Playing with Enumerable.Range (System.Linq)

MSDN Reference: Enumerable.Range Method

I deal with a lot of RANGES at work for a multitude of reasons.
When auditing data and databases, it’s often necessary to check the boundaries of values or to set them.
I’ve recently become very fond of Enumerable.Range because it offers a lot of convenience when dealing with certain types of ranges and can allow a fair amount of complexity.

For instance:
If I need to represent a range of integers from 3 to 17, I could use the construct: Enumerable.Range(3, 15); //3-17
If I need to represent a range of integers from 22 to 24I could use the construct: Enumerable.Range(22, 3); //22-24

…and so on.

Also, I can merge those two non-contiguous ranges with: Enumerable.Range(3, 15).Union(Enumerable.Range(22, 3));
resulting in [3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,22,23,24]

I can also use the  Enumerable set operations for comparisons like: 

Contains(), Intersect(), Union(), Except(), etc.
and a host of other methods included in the class.

The most common action I do with sets and ranges is just a comparison for inclusion or exclusion.
This is of great benefit when comparing a list of numbers to a given
Where I would have previously used Enumerable.Contains(with lambda) to compare a list to a range,
I now use Enumerable.Intersect() as it is easiest to code in all four languages. 

Note:

For carriage-return/linefeeds, I chose to use the Environment.NewLine to avoid having to change the string for each language
using “\n” for some and Chr(10) for VB.

For brevity with the C++, I put the classes in the .cpp file instead of putting the headers in a .h file.

Here are some examples:

C# Calling Program:

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  //
   5:  using EnumerableTest_CPP;
   6:  using EnumerableTest_CS;
   7:  using EnumerableTest_FS;
   8:  using EnumerableTest_VB;
   9:   
  10:  namespace CS_Test_2008_Sept_2010
  11:  {
  12:     class CCS_Test_2008_Sept_2010
  13:     {
  14:        static IEnumerable<int> i_eRange1 = Enumerable.Range(3, 15); //3-17
  15:        static IEnumerable<int> i_eRange2 = Enumerable.Range(22, 3); //22-24
  16:   
  17:        /************************[or this]***************************\
  18:        static IEnumerable<int> i_e =
  19:           Enumerable.Range(3, 15).Union(Enumerable.Range(22, 3));
  20:        \************************************************************/
  21:        static List<int> lst_intList = new List<int>() {
  22:              1,2,3,15,23,77,23,21,8,104,18,19,17
  23:        };
  24:   
  25:        static void Main(string[] args)
  26:        {
  27:           IEnumerable<int> i_eRange = i_eRange1.Union(i_eRange2);
  28:   
  29:           CEnumerableTest_CPP.TestEnumerable(lst_intList, i_eRange, 23);
  30:           CEnumerableTest_FS.TestEnumerable(lst_intList, i_eRange, 23);
  31:           CEnumerableTest_CS.TestEnumerable(lst_intList, i_eRange, 23);
  32:           CEnumerableTest_VB.TestEnumerable(lst_intList, i_eRange, 23);
  33:        }
  34:     }
  35:  }

 

 

 

 

 

 

C++ class Library:

   1:  #include "stdafx.h"
   2:  #include "EnumerableTest.h"
   3:   
   4:  using namespace EnumerableTest;
   5:  using namespace System;
   6:  using namespace System::Collections::Generic;
   7:  using namespace System::Linq;
   8:   
   9:  namespace EnumerableTest_CPP {
  10:   
  11:  public ref class CEnumerableTest_CPP
  12:  {
  13:  public:
  14:      static void TestEnumerable(List<int>^ lst_intFred, IEnumerable<int>^ eFred, int iTarget);
  15:  };
  16:   
  17:  public ref class CCompareInt : IComparer<int>
  18:  {
  19:  public:
  20:      virtual int Compare(int i1, int i2)    { return i1.CompareTo(i2); }
  21:  };
  22:   
  23:  int getInt(int iOrd1){ return iOrd1;}
  24:   
  25:  String^ IntToString(int iChoice){ return iChoice.ToString(); }
  26:   
  27:  void CEnumerableTest_CPP::TestEnumerable(List<int>^ lst_intList, IEnumerable<int>^ i_eRange, int iTarget)
  28:  {
  29:      Console::WriteLine(Environment::NewLine +
  30:          "i_eRange {0:G} my target number",
  31:          Enumerable::Contains(i_eRange, iTarget) ? "contains" : "does not contain");
  32:   
  33:      Console::WriteLine(
  34:          "Display all numbers in lst_intList that are included" + Environment::NewLine + 
  35:          " in the {0:G} digits of i_eRange ranged from {1:G} to {2:G}",
  36:          Enumerable::Count(i_eRange), Enumerable::Min(i_eRange),
  37:          Enumerable::Max(i_eRange)
  38:          );
  39:   
  40:      Console::WriteLine(
  41:          String::Join(",",
  42:              Enumerable::ToArray<String^>(
  43:                  Enumerable::Select( // to convert for the String::Join
  44:                  Enumerable::OrderBy(
  45:                  Enumerable::Intersect(i_eRange, lst_intList),    // Intersect
  46:                          gcnew Func<int,int>(getInt)),    // OrderBy
  47:                          gcnew Func<int, String^>(IntToString)    // Select
  48:                  )    // Select
  49:              )    // ToArray
  50:          )    // Join
  51:      );    // WriteLine
  52:  }
  53:  }

 

 

 

 

 

F# class Library:

   1:  namespace EnumerableTest_FS
   2:  open System
   3:  open System.Collections.Generic
   4:  open System.Linq
   5:   
   6:      module CEnumerableTest_FS =
   7:          let getInt(i1:int) : int =  i1
   8:          let IntToString(i:int) : String = i.ToString()
   9:          //
  10:          let TestEnumerable(lst_intList:List<int>)(i_eRange:IEnumerable<int>)(iTarget:int) =
  11:   
  12:              Console.WriteLine(Environment.NewLine +
  13:                  "i_eRange {0:G} my target number", //ternary in F#
  14:                  (if Enumerable.Contains(i_eRange, iTarget)
  15:                      then "contains" else "does not contain"))
  16:   
  17:              Console.WriteLine("Display all numbers in lst_intList that are included"
  18:                  + Environment.NewLine + 
  19:                  " in the {0:G} digits of i_eRange ranged from {1:G} to {2:G}",
  20:                  Enumerable.Count(i_eRange), Enumerable.Min(i_eRange),
  21:                  Enumerable.Max(i_eRange)
  22:                  );
  23:   
  24:              Console.WriteLine(
  25:                  String.Join(",",
  26:                      Enumerable.Select(
  27:                          Enumerable.OrderBy(
  28:                              Enumerable.Intersect(lst_intList, i_eRange),// Intersect
  29:                              new Func<int,int>(getInt)),// OrderBy
  30:                          new Func<int, String>(IntToString)).ToArray()))// Select

 

 

 

 

 

 

C# class Library:

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:   
   5:  namespace EnumerableTest_CS
   6:  {
   7:     public class CEnumerableTest_CS
   8:     {
   9:        public static void TestEnumerable(List<int> lst_intList, IEnumerable<int> i_eRange, int iTarget)
  10:        {
  11:           Console.WriteLine("i_eRange {0:G} my target number", i_eRange.Contains(23) ? "contains" : "does not contain");
  12:   
  13:           Console.WriteLine(
  14:              "Display all numbers in lst_intList that are included" + Environment.NewLine +
  15:              " in the {0:G} digits of i_eRange ranged from {1:G} to {2:G}",
  16:              i_eRange.Count(), i_eRange.Min(), i_eRange.Max()
  17:              );
  18:   
  19:           Console.WriteLine("{0:G}",
  20:              string.Join(",",
  21:                 lst_intList.Distinct().OrderBy(i => i)
  22:                    .Intersect(i_eRange)
  23:                    .Select(i => i.ToString())
  24:                    .ToArray()));
  25:        }
  26:     }
  27:  }

 

 

 

 

 

 

VB class Library:

   1:  Public Class CEnumerableTest_VB
   2:      Public Shared Sub TestEnumerable(ByVal lst_intList As List(Of Integer), ByVal i_eRange As IEnumerable(Of Integer), ByVal iTarget As Integer)
   3:          Console.WriteLine( _
   4:              Environment.NewLine + _
   5:              "i_eRange {0:G} my target number", _
   6:              If(i_eRange.Contains(23), "contains", "does not contain"))
   7:   
   8:          Console.WriteLine( _
   9:              "Display all numbers in lst_intList that are included" + Environment.NewLine + _
  10:              " in the {0:G} digits of i_eRange ranged from {1:G} to {2:G}", _
  11:          i_eRange.Count(), i_eRange.Min(), i_eRange.Max())
  12:   
  13:          Console.WriteLine("{0:G}", _
  14:              String.Join(",", _
  15:              lst_intList.Distinct().OrderBy(Function(i) i) _
  16:              .Intersect(i_eRange) _
  17:              .Select(Function(i) i.ToString()) _
  18:              .ToArray()))
  19:      End Sub
  20:  End Class
 
 
OUTPUT from the run:
Enumerable.Range 

 

 

 

 

 

posted @ Wednesday, September 8, 2010 3:18 PM
Print

Comments on this entry:

No comments posted yet.

Your comment:



(not displayed)

 
 
 
 

Live Comment Preview:

 
«November»
SunMonTueWedThuFriSat
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567