I have an integer range I need to check against, but the field I'm using for the comparison is a string.
This string could have non-integer values in it. Strings with non-integer values should be skipped.
The range is simply two other integers.
I want to know what the fastest way to do this is, if there are ten thousand numbers in the list of strings. I've considered simply int.TryParse, and then conditional checks between the range, but I want to know if there is a faster way to do it.
Not looking for opinions, keen to see benchmark numbers.
Below is an example of what the data and range min/max might look like.
int min = 1000;
int max = 4999;
List<string> orderNumbers = new List<string>
{
"4021",
"*1002",
"5000",
"4500"
};
TryParse
would work well
var results = orderNumbers
.Select(x => int.TryParse(x, out var i) ? i : (int?) null)
.Where(x => x >= min && x <= max)
.Cast<int>() // resolve the nullable;
Note : you could easily use .Select(x => x.Value)
it will essential create the same exact IL
If you are doing this often, then ideally your list wouldn't be of type string
.
Or just use a foreach
loop
var results = new List<int>(orderNumbers.Count);
foreach (var item in orderNumbers)
if (int.TryParse(item, out var value) && value >= min && value <= max)
results.Add(value);
If you are bored, create your own Iterator extension method
public IEnumerable<int> GetRange(this IEnumerable<string> source, int min, int max)
{
foreach (var item in source)
if (int.TryParse(item, out var value) && value >= min && value <= max)
yield return value;
}
Usage
var results = orderNumbers.GetRange(min,max);
If you were looking at raw efficiency, and your valid numbers were always just numbers with no cultural differences like 1000's separators and such. You may get better performance out of your own TryParse
method and (optionally) iterating chars with pointers or Span<T>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe bool MyTryParse(string source, int min, int max, out int value)
{
value = 0;
fixed (char* p = source)
{
for (var i = 0; i < source.Length; i++)
if (p[i] >= '0' && p[i] <= '9')
value = value * 10 + p[i] - '0';
else
return false;
}
return value >= min && value <= max;
}