我有一份要评估的文件编号清单。这个列表非常大,我宁愿不将所有文档编号都转换为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语句来进行转换和比较),但我关注的是性能这一点,因为返回时列表可能相当大。
我对这里的建议持开放态度,并且知道可能有许多路径都会导致相同的结果。我关注的主要问题是 性能 。请记住,我可以在非常大的数据集上执行此操作,我需要在合理的时间内返回结果。
提前感谢您提出任何建议。
~~~编辑~~~
我正在利用的对象是QuickBooks Online的Intuit IPP SDK对象。我正在查询文件(例如发票)并需要对文件编号进行排序。 Intuit不会在他们的服务器端执行此操作,因此我必须在我这边做。根据用户输入的其他搜索条件,我可能会在返回的列表中找到所有文档。
答案 0 :(得分:1)
创建自己的比较器,比如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”为整数,但这只有在你处理一次文档列表然后多次查询时才有意义。
预处理的简单解决方案是从Dictionary<string, int>
字符串值和解析的数字值创建Header.DocNumber
。对于不解析的值,您可以使用-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;
设置此词典需要一些额外的时间,但如果您多次查询同一文档集,它将会收回。
答案 1 :(得分:0)
当您获得范围时,请使用空格左键填充起始编号,使其与结束编号的长度相同。所以在你的例子中,你的结尾数字是“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;