将字符串整数与 C# 中的范围进行比较的最有效方法

Most efficient way to compare a string integer against a range within C#

我需要检查一个整数范围,但我用于比较的字段是一个字符串。

此字符串中可能包含非整数值。应跳过具有非整数值的字符串。

范围只是另外两个整数。

我想知道如果字符串列表中有一万个数字,最快的方法是什么。我考虑过简单地int.TryParse,然后在范围之间进行条件检查,但我想知道是否有更快的方法

不寻求意见,热衷于查看基准数据。

下面是数据和范围 min/max 的示例。

int min = 1000;
int max = 4999;

List<string> orderNumbers = new List<string>
{
    "4021",
    "*1002",
    "5000",
    "4500"
};

TryParse 效果不错

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;

:你可以很容易地使用 .Select(x => x.Value) 它必须创建完全相同的 IL


如果您经常这样做,那么理想情况下您的列表不会是 string.

类型

或者只使用 foreach 循环

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);

如果你无聊,创建你自己的迭代器扩展方法

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;
}

用法

var results = orderNumbers.GetRange(min,max);

如果您正在查看原始效率,并且您的有效数字始终只是没有文化差异的数字,例如 1000 的分隔符等。您可能会从自己的 TryParse 方法和(可选)使用指针或 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;
}