Drag the delimited string to the <int> list
If I have, for example, the following line:
"123; 3344; 4334; 12"
and I want these numbers to be in general List<int> , I think I don’t know a good way here except to break in a loop and do the conversion, and then add to List<int> through each iteration. Does anyone have other ways to do this?
Update. Here is what I came up with. I want to do it the old way, and not with LINQ, because I try to improve with just strings, arrays, lists, and manipulation and conversion in general.
public List<int> StringToList(string stringToSplit, char splitDelimiter) { List<int> list = new List<int>(); if (string.IsNullOrEmpty(stringToSplit)) return list; string[] values = stringToSplit.Split(splitDelimiter); if (values.Length <= 1) return list; foreach (string s in values) { int i; if (Int32.TryParse(s, out i)) list.Add(i); } return list; } This is a new command line method that I plan to use when I need to convert a list of delimited strings to a list
So, I return an empty list to the caller if something fails. Good bad? is it quite common for this?
Yes, there are more “elegant” ways to do this with LINQ, but I want to do it manually .. as before, now only for my own understanding.
Also, what bothers me:
list.AddRange(str.Split(';').Select(Int32.Parse)); lies in the fact that I have no idea:
- How to put it in TryParse.
- What if
str.Split(';').Select(Int32.Parse)just doesn't work for some reason ... then the method that this AddRange is in will explode, and if I don't add a try / trick around of all this, I will be screwed up if I don't handle it correctly.
string str = "123;3344;4334;12"; List<int> list = new List<int>(); foreach (string s in str.Split(';')) { list.Add( Int32.Parse(s)); } static int? ToInt32OrNull(string s) { int value; return (Int32.TryParse(s, out value)) ? value : default(int?); } // ... var str = "123;3344;4334;12"; var list = new List<int>(); list.AddRange(str.Split(';') .Select(ToInt32OrNull) .Where(i => i != null) .Cast<int>()); Notes for participants:
I do not know anything good here, except how to break in a loop and do the conversion, and then add to the list
In general, this is the main reason LINQ was added to C # - to eliminate the need to work with sequences of values by implementing loops and instead simply declare their intention to convert the sequence. If you ever thought: “I don’t know how to do this except with a loop” - it's time to take a look at the LINQ construct that will work for you.
Performance Update:
Below is a description of LINQ performance. Although the LINQ idea is more slowly defended in the comments, as we get the benefits of readability, maintainability, and layout, there is another aspect that gives LINQ an easy performance advantage: parallelism. Here is an example where adding only one extension method call, AsParallel() doubles the performance. This is a great example of where scaling outperforms microoptimization without even requiring a thorough assessment. Note. I am not saying that micro-optimizations are not needed, but with the tools that we have at this level of distraction, the need becomes vanishingly small.
class Program { private const int ElementCount = 10000000; static void Main(string[] args) { var str = generateString(); var stopwatch = new Stopwatch(); var list1 = new List<int>(ElementCount); var list2 = new List<int>(ElementCount); var split = str.Split(';'); stopwatch.Start(); list1.AddRange(split .Select(ToInt32OrNull) .Where(i => i != null) .Cast<int>()); stopwatch.Stop(); TimeSpan nonParallel = stopwatch.Elapsed; stopwatch.Restart(); list2.AddRange(split .AsParallel() .Select(ToInt32OrNull) .Where(i => i != null) .Cast<int>()); stopwatch.Stop(); TimeSpan parallel = stopwatch.Elapsed; Debug.WriteLine("Non-parallel: {0}", nonParallel); Debug.WriteLine("Parallel: {0}", parallel); } private static String generateString() { var builder = new StringBuilder(1048576); var rnd = new Random(); for (int i = 0; i < ElementCount; i++) { builder.Append(rnd.Next(99999)); builder.Append(';'); } builder.Length--; return builder.ToString(); } static int? ToInt32OrNull(string s) { int value; return (Int32.TryParse(s, out value)) ? value : default(int?); } } Non-parallel: 00: 00: 07.0719911
Parallel: 00: 00: 04.5933906
List<int> list = (from numString in "123;3344;4334;12".Split(';') select int.Parse(numString)).ToList(); string myString = "123;3344;4334;12"; var ints = new List<int>(); (from s in myString.Split(';') select int.Parse()).ToList().ForEach(i=>ints.Add(i)); I heard .Net 4.0 could add ForEach to Enumerable<T> , so ToList might be unnecessary there (can't check).
I think this is the easiest
var str = "123;3344;4334;12"; var list = str.Split(';').ToList().Cast<int>();