C#: Splitting Data From a String and Extracting out Decimals and Integers into Separate Lists Using Extension Methods
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.
Good article. Lambdas are the one thing I have to revisit every time I see one to be able to read them.
data.Select(itm => Decimal.Parse(itm))
is equivalent to:
data.Select(Decimal.Parse)
Sorry Yassin, .Select(Decimal.Parse) does not compile, the compiler can’t infer the type.
Sorry for the mistake! Btw, very nice blog!
I truly appreciate the feedback. I make mistakes in the MSDN forums and if there is a correct, or even better way; I am for hearing it!
Just a small comment on your statement that an IEnumerator is another form for list;
i would put it like this: An list is an IEnumerator but an IEnumerator doesn’t have to be a list.
You are typically able to add things to a list, refer to its items by indexing and easily get a total count of items which is not easily done with an IEnumerator (and adding items is not possible at all).
It can seem easy with the use of Linq, but one has to understand that for example .Count() actually has to run through all items. Basicly all you can do with an IEnumerable is doing a foreach loop and getting the 105th item makes the iterator do a foreach 104 times.