Posts Tagged Select

Sometimes you have the need to extract text out of a string, once extracted you need to get the right data into lists. Say one list of integers and one list of decimals. Using the extension methods now found in .Net one can easily do those operations.

Example

Here is the data in a string, “12 34 56.1 18 19.25 41”. We want the integers separated out from the decimals into their own lists respectively as their native values (int/decimal) and not strings. Using Where, Select and a couple of Lambdas we can get to the intended  result.

```string data =@"12 34 56.1 18 19.25 41";

string[] dataAsStrings = data.Split( ' ' );

List<decimal> decs = ( dataAsStrings.Where( itm => itm.Contains( '.' ) ) )
.Select( itm => Decimal.Parse( itm ) )
.ToList();

List<int> ints = ( dataAsStrings.Where( itm => itm.Contains( '.' ) == false ) ).Select( itm => int.Parse( itm ) ).ToList();

foreach ( decimal dc in decs )
Console.WriteLine( dc );
/* Outputs 56.1 19.25 (on seperate lines)*/

foreach ( int it in ints)
Console.WriteLine( it );
/* Outputs 12 34 18 41 (on seperate lines)*/```
• Step one is top split the string using string.Split.
• Step 2 is take that split data and enumerate over it using the Where method.
• Within the Where we use a lambda which basically says for each item in the list, if it contains a period select it and return it. Note the result of most Extension methods is deemed a projection which is really a list of the values. Where, Select and ToList all return projections.
• Once the Where is done we call/chain the Select Extension. The select is saying take the projection from the Where and on each item parse out the value and return it in its native, non string format.
• Using the ToList on the projection created by the Select we take the items and specify it to be in a List<> format.

We didn’t have to do the ToList and could have said something like this:

```var decs = ( dataAsStrings.Where( itm => itm.Contains( '.' ) ) )
.Select( itm => Decimal.Parse( itm ) );
foreach ( decimal dc in decs )
Console.WriteLine( dc );
/* Outputs 56.1 19.25 (on seperate lines)*/```

Which would have been just as vaild. At runtime the var would have been internally known as IEnumerable<decimal> under the covers and as you can see that is just a different type of list and works just the same.

(Updated 3/26/2011 works on .Net 3-4)

In C# 3.0 (.Net 3.5/4.0) one can use the extension methods which work on IEnumerables to help with processing or converting your generic lists. This quick article shows how one can quickly join a list of integers and print them out as one sentance of “1 2 3 4 5”. Obviously there are other ways of doing this, but this gives one an overview.

Select Extension to Project Our List To Strings

Since the generic List<> inherits from IEnumerable we can use its extension methodd to do our dirty work. Look at the code here:

```List<int> items = new List<int>() { 1, 2, 3, 4, 5 };

Console.WriteLine
(
string.Join
( " ",
items.Select(
item => item.ToString()
).ToArray()
)
);```
• Line 01: Here is our list of integers which we will want to eventually convert to a string “1 2 3 4 5”.
• Line 05: The old static string.Join will do our dirty work by joining each of the items with a space for better reading. We just have to get it an oldstyle string array to it though.
• Line 07: The extension Select method, will project (enumerate) over each item within our integer array and we will specify a new projection of strings using a lambda.
• Line 08: Here is the lamda function which basically tells the compiler that for each now named item in items; simply convert it to its string counterpart.
• Line 09: *Sigh* as mentioned above, string.Join needs the old style array, do that conversion here with the help of antoher extension!

Without String.Join Using Another Extension Method Aggregate

To remove the need of string.Join we will use the extension method Aggregate. Aggregate allows us to accumulate or aggregate values. Let me explain in code to achieve the same results as above:

```List<int> items = new List<int>() { 1, 2, 3, 4, 5 };

Console.WriteLine
(
items.Select( item => item.ToString() )
.Aggregate<string, string>
(
string.Empty,
( string prev, string current )
=> prev +
(prev == String.Empty ? current : " " + current)
)
);```
• Line 05: We again use the Select extension/projection to convert our integers into string numbers.
• Line 06: The aggregate method applies/projects an accumulator Lambda functon of our specification over the list of strings. Think of the Aggregate method as one which is stateful, for we will receive the results of the previous operation and be able to join it to the current. Line 04 simply tells the compiler that are working with two strings on input and output. One string is the previous aggregation operation and the other is the current item in the list being enumerated over during its processing.
• Line 08: Since our aggregate takes two strings, we need to seed the process. The first call will use this string.Empty which will act as the first previous value to be married to the first current item in the projection/enumeration.
• Line 09: This begins our declaration of the lamda function to use, it expects two strings, a previous accumulated string value and the current string item in the projection.
• Line 10: What ever came before, we are going to marry it to the current. Here is why we need to seed string.Empty into the very first call.
• Line 11: The previous will be married to the current, but we need to anticipate the very first time it is run where the string will be empty. For that situation, just return the current value. Otherwise return the current value with a space such as ” 2″. That will be then be concatenated (+) to prev in line 8. This is where we simulate the string.Join.

There you go a few ways of using the extension methods of Select and Aggregate and toArray with their specific individual lamda functions in C#.