July 20, 2017

A String.Split() That Returns An IEnumerable

A version of Split string that returns an IEnumerable<string> rather than an array. Only single separate string is allowed, it is very rare that an array of separator strings is required.
  
public static class StringSplitExtensions
{
  
  public static IEnumerable<string> Split2(
    this string targetStr,
    string separator )
  {
    if ( targetStr == null )
      yield break;

    if ( string.IsNullOrEmpty( separator ) )
    {
      yield return targetStr;
    }
    else
    {
      string str = targetStr;
      bool finished = false;
      int startIx = 0;
      int sepLength = separator.Length;
      while ( !finished )
      {
        var ix = str.IndexOf( separator, 
            StringComparison.OrdinalIgnoreCase );
        if ( ix == -1 )
        {
          finished = true;
          yield return str;
        }
        else
        {
          string res = str.Substring( 0, ix );
          yield return res;
          startIx = ix + sepLength;
          str = str.Substring( startIx, str.Length - startIx );
        }
      }
    }
  }
}



[ Test ]
public void SplitTest()
{
  string test = "012 3456\t7890\ta  aaa\tbbbb\t";

  var res2 = test.Split2( "\t" ).ToArray();
  var norm2 = test.Split( '\t' );
  Assert.IsTrue( AreTheSame( res2, norm2 ) );

  var res3 = "".Split2( "\t" ).ToArray();
  var norm3 = "".Split( '\t' );
  Assert.IsTrue( AreTheSame( res3, norm3 ) );

  var res4 = "\t".Split2( "\t" ).ToArray();
  var norm4 = "\t".Split( '\t' );
  Assert.IsTrue( AreTheSame( res4, norm4 ) );

  var res5 = "\t\t".Split2( "\t" ).ToArray();
  var norm5 = "\t\t".Split( '\t' );
  Assert.IsTrue( AreTheSame( res5, norm5 ) );

  var res6 = "a\t".Split2( "\t" ).ToArray();
  var norm6 = "a\t".Split( '\t' );
  Assert.IsTrue( AreTheSame( res6, norm6 ) );

  var res7 = "\ta".Split2( "\t" ).ToArray();
  var norm7 = "\ta".Split( '\t' );
  Assert.IsTrue( AreTheSame( res7, norm7 ) );

  // Works the same as a standard Split string except in 
  // the case where the Splitter string is an empty string
  var norm8 = test.Split();
  var res8 = test.Split2( "" ).ToArray();
  Assert.IsFalse( AreTheSame( res8, norm8 ) );
}


// Checks whether 2 string arrays are exactly the same, ie. they have
// the same length and the same values at each array entry
public static bool AreTheSame(
string[] stringArray1,
string[] stringArray2)
{
  bool areTheSame = (stringArray1.Length == stringArray2.Length);
  for (int ix = 0; (ix < stringArray1.Length) && areTheSame; ix++)
  {
    areTheSame = stringArray1[ix].Equals(stringArray2[ix], StringComparison.CurrentCulture);
  }
  return areTheSame;
}

No comments: