0

    我有一个要评估的文件编号列表。这个列表非常大,我不想将所有文档编号都转换为 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 不在他们的服务器端执行此操作,因此我必须在我方执行此操作。根据用户为其他搜索条件输入的内容,我最终可能会将他们的所有文档都放在返回的列表中。

4

2 回答 2

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;

设置这个字典需要一些额外的时间,但如果你多次查询同一个文档集,它会得到回报。

于 2013-03-06T16:26:30.643 回答
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;
于 2013-03-06T16:26:51.000 回答