由于字符串比较导致文档号计算不正确
本文关键字:文档 计算 不正确 字符串 比较 | 更新日期: 2023-09-27 18:02:29
我有一个要评估的文档编号列表。这个列表非常大,我不想将所有文档号都强制转换为int型,因为它们也可能包含字母。以下是一个示例数字列表。
1070
1071
1072
1073
1074
1075
1076
1077
1078
CO1089
CO1099
CO2000
这些数字包含在c#的对象中,我运行Linq来返回Range中的对象列表。这是我的linq代码。
results = from row in MyObjectList.AsQueryable<MyObject>()
where String.Compare(row.Header.DocNumber, _sDocumentStartNumber) >= 0
&& String.Compare(row.Header.DocNumber, _sDocumentEndNumber) <= 0
select row;
如果我有一个范围: 1
: ,,,,, 10000,
用户希望返回该范围内所有数字编号的事务。然而,因为我比较字符串,我没有得到任何结果。
我可以检测到我的to和from值是数字,然后只计算与数字有关的事务,并在此基础上使用linq语句(或编辑linq语句来进行转换和比较),但此时我关心的是性能,因为返回时列表可能相当大。
我愿意听取建议,也知道可能有很多途径都通向同样的结果。我最关心的是性能。请记住,我可以在非常大的数据集上执行此操作,并且我需要在合理的时间内返回结果。
提前感谢您的任何建议。
~~~编辑
我利用的对象是Intuit IPP SDK对象QuickBooks Online。我正在直观地查询文档(如发票),并且需要对文档编号进行排序。Intuit没有在他们的服务器端做这个,所以我必须在我的服务器端做这个。根据用户输入的其他搜索条件,我可以在返回的列表中得到他们所有的文档。
创建自己的比较器,例如DocumentNumberWithinRangeComparer
:
public class DocumentNumberWithinRangeComparer
{
public int? RangeFrom { get; set; }
public int? RangeTo { get; set; }
public DocumentNumberWithinRangeComparer(int? from, int? to)
{
RangeFrom = from;
RangeTo = to;
}
public bool IncludeInResults(MyObject obj)
{
if (!RangeTo.HasValue || !RangeFrom.HasValue)
return true;
int docnumber;
if (!Int32.TryParse(obj.Header.DocNumber, out docnumber))
return false;
return docnumber >= RangeFrom.Value && docnumber <= RangeTo.Value;
}
}
然后创建一个实例并使用它来过滤:
var comparer = new DocumentNumberWithinRangeComparer(0,100);
var results = from row in MyObjectList.AsQueryable<MyObject>()
where comparer.IncludeInResults(row)
select row;
如果你想要更快的比较,你应该预处理你的"DocNumber"为整数,但这只有在你处理一次文档列表然后多次查询它时才有意义。
预处理的一个简单解决方案是从Header.DocNumber
字符串值和解析的数字值创建Dictionary<string, int>
。对于不能解析的值,可以使用-1
、Int32.MinValue
之类的东西,或者使用更高级的解析器来处理非数值。
一旦你有了字典,你可以像这样查询…
var dictionary = new Dictionary<string, int>(); // Fill this...
var results = from row in MyObjectList.AsQueryable<MyObject>()
where dictionary[row.Header.DocNumber] >= _sDocumentStartNumber &&
dictionary[row.Header.DocNumber] <= _sDocumentEndNumber
select row;
设置这个字典将花费一些额外的时间,但是如果您多次查询同一个文档集,这将是值得的。
当您获得范围时,用空格左填充开始数字,使其与结束数字相同的长度。在你的例子中,你的结束数字是"10000"。因此,将您的起始数字设置为"__1"(即4个空格,然后一个1)。
比较时,在比较前左加文档号。所以:
string paddedStart = _sDocumentStartNumber.PadLeft(_sDocumentEndNumber.Length);
string padded;
results = from row in MyObjectList.AsQueryable<MyObject>()
let padded = row.Header.DocNumber.PadLeft(paddedStart.Length)
where String.Compare(padded, paddedStart) >= 0
&& String.Compare(padded, _sDocumentEndNumber) <= 0
select row;