Posts Tagged Foreach

LINQ on String using the IEnumerable<char> Interface


Introduction

This post is about using LINQ across (or more to the point within the) String Objects. Rather than, the more common, using Strings in LINQ expressions, this blog post focus on using the string object’s representation as a Char array (which is the way I think of the representation – a hangover from being a long term C/C++ programmer) in LINQ expressions. For the pedants, and to be exactly precise, it is the IEnumerable<char> interface of the String Object which enable the use of LINQ on the contents of a String Object.

I suspect that some C# developers may not have spotted that there are opportunities which the IEnumerable<char>  interface of a string offers.

The following are three methods are examples of using the IEnumerable<char> representation of a string to do some fairly common string manipulations.

Code Examples

Camel Case

This is quick proper case (or camel case) routine. The rule here was simple if there are less than four tokens in the input string, make the first character of each token upper case. There is “bit” of “fancy dancing” to get the desired result. For each of the tokens, select the upper case of the first character plus the balance of the string with a trailing space, then roll up the strings into a aggregate, then make a char array of the aggregate, make a new string , and finally trim off the trailing space. Not really heavily leveraging the IEnumerable<char> representation of the string, but shows what can be done.

private string ProperCase(string InfoLine)
{
    char[] delimiters = { ' ' };
    string[] tokens = InfoLine.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);
    if (tokens.Length < 4)
    {
        return new string(
            tokens.Select(A => Char.ToUpper(A[0]) + A.Substring(1) + " ")
            .Aggregate((A, B) => A + B).ToArray()).Trim();
    }
    else
    {
        return InfoLine;
    }
}

A Quick QName

This one is used to make a synthetic QName (reference to Wikipedia QName and W3C XML QName definition) which does make use of working at with the IEnumerable<char> representation of the String Class. It’s intention is to throw away all but the standard characters (could/should use char.IsLetter, but this version does what all that I wanted at the time).

private string MakeQName(string Name)
{
    // simple compress spaces out
    return new String(Name.Where(A => !Char.IsPunctuation(A) && !Char.IsSeparator(A)).ToArray());
}

Extracting Number and Text From a String

This is another example of the use of the IEnumerable<char> aspect of the string class. This case does the following:

  • Pulls a long, or double, value from a string.
  • Then the process pulls a unit of quantity from the string as well (the residual text in the string).

This example builds the resulting string up character by character in a StringBuilder object (another way to make the transition from a character by character representation of a string back into string).

private void PullNumberAndUnit(string CompoundValue, out string SizeString, out SizeUnits sizeUnits)
{
    StringBuilder buf = new StringBuilder();
    String strSize;
    long lSize = 0L;
    string strUnit;
    if (CompoundValue.IndexOf(".") == -1)
    {
        CompoundValue.Where(A => Char.IsDigit(A)).ToList().ForEach(A => buf.Append(A));
        strSize = buf.ToString().Trim();
        if (long.TryParse(strSize, out lSize))
        {
            SizeString = lSize.ToString();
        }
        else
        {
            SizeString = String.Empty;
        }
    }
    else
    {
        CompoundValue.Where(A => Char.IsDigit(A) || A == '.').ToList().ForEach(A => buf.Append(A));
        strSize = buf.ToString().Trim();
        double dVal = 0.0;
        if (double.TryParse(strSize, out dVal))
        {
            SizeString = dVal.ToString();
        }
        else
        {
            SizeString = String.Empty;
        }
    }
    buf.Clear();
    CompoundValue.Where(A => !Char.IsDigit(A)).ToList().ForEach(A => buf.Append(A));
    strUnit = buf.ToString().Trim();
    if (this.DecodeUnits.ContainsKey(strUnit))
    {
        sizeUnits = DecodeUnits[strUnit];
    }
    else
    {
        sizeUnits = SizeUnits.Unknown;
    }
}

Conclusions

I hope that the above examples provide some inspiration, or a quick solution to a knotty problem.

Have fun with LINQ and string. There are bound to be a multitude of other ways the representation (or for the pedants reading this interpretation) of a string as a character array can be “gainfully employed” by C# developers. These are just some of samples, of the application of this technique, that way I’ve found (thus far – next development task could have some more waiting to be found).

Some of my previous LINQ Posts

 

 

 







		
Advertisements

, , , , , ,

6 Comments

Using the ForEach Method


Introduction

I’ve found a new “toy” in the C# language this week, the Foreach extension method. It seems to me to be a very effective way of expressing some of those short “iterate over an x and do something to the members.

I’ve always been a bit “frustrated” with C# when it comes to iterating over collections. The foreach syntax is fine, when you’re doing a loop which has some complex logic. But, for short sharp thing, has always seemed to be a few too many keystrokes for the results. Sure, there is the code snippet for foreach which cuts down the keystrokes, but you still have the minimum of 2 lines of code, or 4 if you us { and }. Also my “inbuilt style guide” baulks at putting multiple statements on one line.

foreach (string part in TransactionTriggers) Debug.WriteLine(String.Format(" [{0}] ", part));

Or

foreach (string Name in AllNames.Distinct().OrderBy(A => A))
{
    Debug.WriteLine(Name);
}

Oops, the above includes some of my abuses of LINQ. Doing a Distinct and then sorting the list, probably stretching the friendship with LINQ. But, what the heck it works 😉 !

Using the Foreach Extension Method

TokenList.ForEach(a => Debug.WriteLine(a));

the above is a quick dump of the contents of a List>String< to the debug console.

private List LookupType(DataElementsDataContext deDC, List InformationDataElements)
{
    List<string> result = new List>string<();
    InformationDataElements.ForEach(A => result.Add(LookupType(deDC, A)));
    return result;
}

An example of method invocation and adding to a list. I’ve also used LINQ to achieve the same sort of result:

var log1 = from line in ParsedLines
           select new LogMessage(line);

 

StringBuilder result = new StringBuilder();
bool First = true;
InformationNameDetails.ForEach(A =>
    {
    if(First)
        First = false;
    else
        result.Append(" and ");
    result.Append(A);
}
);

It is probably an abuse of the lambda expressions to include chunks of procedural logic. But, again it works for me, so what the heck!

Conclusions

There are more than one observatins which should be made at this point. The major ones are:

  • The use of the Foreach extension method certainly, seems to me, to be an effective way of “cleaning up” C# code, and removing some of the padding which is necessary for the foreach statement.
  • The Foreach extension method is something which could be over used. Well more to the point the complexity of the lambda expression could get greater than the language designers intended.
  • Moving to the method syntax for some foreach loops, opens the door to using the Parallel ForEach Method from the System.Threading.Tasks namespace. You’ve done most of the hard work in the writing of the lambda expression. What is left in the move to a parallel ForEach is a lot of work making sure that what you’re invoking can be done in a parallel manner safely.

References:

, , , , , , , , , , , ,

2 Comments

LINQ SelectMany and IGrouping


Introduction

This post is prompted by the the following:

Some Examples of SelectMany

The following C# code demonstrates SelectMany being used in a coupe of different ways. I’ve collated example from a couple of sources here (Nick’s Blog, MSDN, and StackOverflow). They demonstrate a couple of different ways to use the SelectMany LINQ extension method.

    namespace SelectMany1
    {
        class PetOwner
        {
            public string Name { get; set; }
            public List<String> Pets { get; set; }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                Sample1();  // Taken from Nick Olsen's blog  http://nickstips.wordpress.com/2010/07/26/linq-flatten-a-list-of-lists/
                Sample2();  // Taken from 
                Sample3();  // Taken from MSDN http://msdn.microsoft.com/en-us/library/bb534336.aspx
            }
    
            private static void Sample3()
            {
                PetOwner[] petOwners = 
                        { new PetOwner { Name="Higa, Sidney", 
                              Pets = new List<string>{ "Scruffy", "Sam" } },
                          new PetOwner { Name="Ashkenazi, Ronen", 
                              Pets = new List<string>{ "Walker", "Sugar" } },
                          new PetOwner { Name="Price, Vernette", 
                              Pets = new List<string>{ "Scratches", "Diesel" } } };
    
                // Query using SelectMany().
                IEnumerable<string> query1 = petOwners.SelectMany(petOwner => petOwner.Pets);
    
                Console.WriteLine("Using SelectMany():");
    
                // Only one foreach loop is required to iterate 
                // through the results since it is a
                // one-dimensional collection.
                foreach (string pet in query1)
                {
                    Debug.WriteLine(pet);
                }
            }
    
    
            private static void Sample1()
            {
                List<List<string>> listOfLists = new List<List<string>>();
                listOfLists.Add(new List<string>() { "a", "b", "c" });
                listOfLists.Add(new List<string>() { "d", "e", "f" });
                listOfLists.Add(new List<string>() { "g", "h", "i" });
    
                var flattenedList = listOfLists.SelectMany(x => x);
                Debug.WriteLine("Sample 1");
                foreach (string s in flattenedList)
                    Debug.Write(s + " ");
                Debug.WriteLine(" ");
                //Sample 1
                //a b c d e f g h i  
            }
    
            private static void Sample2()
            {
                // Finding duplicates in a list of string
                List<String> list = new List<String> { "6", "1", "2", "4", "6", "5", "1" };
                var duplicates = list.GroupBy(s => s).SelectMany(grp => grp.Skip(1));
                Debug.WriteLine("Sample 2");
                foreach (string s in duplicates)
                    Debug.Write(String.Format("{0} ", s));
                Debug.WriteLine(" ");
                //Sample 2
                //6 1 
            }
    
        }
    
  • Sample 1: shows the way that SelectMany can unwrap a list of lists into a list.
  • Sample 2: shows an interesting way of detecting duplicates. This solution returns a list of the strings with more than 1 occurrence (Skip(1)), as a list of n-1 copies of string (where n is the number of times that string occurs). So if you just want the duplicated string (occurring only once), put a Distinct() after the SelectMany. This example also invokes an interesting property of the GroupBy and what is returned the IGrouping interface, I’ll comment on that below.
  • Sample 3: Is a demonstration of a lambda expression working within a class which contains a list.  

IGrouping – The output from LINQ GroupBy

This is the output from the LINQ GroupBy extension method. The example 2 lead me to ponder “How does it work?”. Having worked with (around) the LINQ GroupBy extension method previously, I knew that there was a Key property, and a list of contributors to the group. So, how did the Skip(1) work?

It turns out that IGrouping is a bit of an “interesting animal”. The description of the interface is as follows:

public interface IGrouping<out TKey, out TElement> : IEnumerable, IEnumerable

The IEnumerableis the key to how the Skip(1) works. The GroupBy result is being read as series of list, one for each of the keys (I think, I could be wrong). 

 

, , , , , , , , ,

3 Comments

%d bloggers like this: