C# 在哪里我该如何加速?

C# 在哪里我该如何加速?,c#,arrays,linq,collections,.net-3.5,C#,Arrays,Linq,Collections,.net 3.5,假设我有一门课是这样的: class ItemLimits { public string strAccountNumber = string.Empty; public string strUserCode = string.Empty; public long lAccumulatedAmount = 0L; } 我有一个包含50000个元素的数组 我还有一个50000个项目(或多或少)的数据集,我需要在itemlimites数组中找到与此数据集匹配的元素 目前正在通过以下数据

假设我有一门课是这样的:

class ItemLimits
{
  public string strAccountNumber = string.Empty;
  public string strUserCode = string.Empty;
  public long lAccumulatedAmount = 0L;
}
我有一个包含50000个元素的数组

我还有一个50000个项目(或多或少)的数据集,我需要在
itemlimites
数组中找到与此数据集匹配的元素

目前正在通过以下数据集循环执行此操作:

ItemLimits ilItemLimit = itemlimits.Where(s => s.strUserCode.Equals(dataset[i].User_UserCode, StringComparison.CurrentCultureIgnoreCase)
                      && s.strAccountNumber.Equals(strUnEditedHomingAccountNo, StringComparison.CurrentCultureIgnoreCase)).First();
strUnEditedHomingAccountNo
是先前从数据集获取的

一旦我找到了我需要的
ItemLimit
,我需要添加到它的
lAccumulatedAmount

我从我的性能基准中看到,这在循环开始时非常快,但随着时间的推移会变慢。这是一个线性减速,你可以在我制作的图表中看到:

当我达到40000件物品时,每件物品大约需要40毫秒才能完成。这在我的头脑中是有意义的,因为我假设它只是一个接一个地迭代项目,直到找到匹配项,对于大量的项目,这显然是相当缓慢的

数组和数据集中的项目数可能会有很大的差异

我曾考虑尝试对数组进行排序并执行
array.BinarySearch
,但由于
struercode
strAccountNumber
都可以更改,而且我也无法预测数据集的顺序,因此我不知道如何最有效地排序

这是程序中最慢的部分,这就是为什么我想尝试优化它(大约70%的时间都花在做这件事上,还有很多其他的事情要做)

如果有人能给我指点我能做什么,我将不胜感激


我正在使用.NET 3.5,我无法改变这一点。

我认为您对导致此问题的原因是正确的,我建议您使用具有快速查找功能的工具来加快速度。有点像字典,速度很快。你已经知道如何比较,看看你是否有正确的记录,你也只寻找一个匹配,或第一个

尝试类似的方法,您需要更改数据集的类型(不知道您正在使用什么),并可能决定在制作
itemLimitDictionary
时如何处理键冲突,但除此之外,它应该可以很好地加快速度:

public void DoTheNeedfull(ItemLimit[] itemLimits, DataSet dataSet)
{
    var itemLimitDictionary = itemLimits.ToDictionary(i => MakeKey(i.One, i.Two), i => i);

    for(var i = 0; i < dataSet.Count; i++)
    {
        var strUnEditedHomingAccountNo = BlackMagicMethod(dataSet[i]);
        var key = MakeKey(dataSet[i].User_UserCode, strUnEditedHomingAccountNo);

        if(itemLimitDictionary.ContainsKey(key))
        {
            // do your thing
        }
        else
        {
            // maybe this is an error
        }
    }
}

private string MakeKey(string keyPartOne, string keyPartTwo)
{
    return keyPartOne.ToUpperInvariant() + keyPartTwo.ToUpperInvariant();
}
public void DoTheNeedfull(ItemLimit[]itemLimits,数据集)
{
var itemLimitDictionary=itemLimits.ToDictionary(i=>MakeKey(i.One,i.Two),i=>i);
对于(var i=0;i
据我所知,您喜欢遍历数据集,而不是增加计数器。该计数器特定于数据集条目的某些属性


所以这听起来像是
GroupJoin()
linq语句的工作。这样,您将得到一个ItemLimits对象,其中所有匹配的数据集项都是
IEnumerable
。然后,您可以在此内部枚举上调用
Aggregate()
,并将此信息写入给定的
ItemLimits
对象。

我已经完全放弃了
中的
位置,并使用
数组完成了此操作。使用此比较器进行BinarySearch

class ItemLimitsComparer : Comparer<ItemLimits>
  {
    public override int Compare(ItemLimits x, ItemLimits y)
    {
      if(Convert.ToInt32(x.strUserCode) < Convert.ToInt32(y.strUserCode))
      {
        return -1;
      }
      if(Convert.ToInt32(x.strUserCode) > Convert.ToInt32(y.strUserCode))
      {
        return 1;
      }
      if(Convert.ToInt32(x.strUserCode) == Convert.ToInt32(y.strUserCode))
      {
        if(Convert.ToInt64(x.strAccountNumber) < Convert.ToInt64(y.strAccountNumber))
        {
          return -1;
        }
        if(Convert.ToInt64(x.strAccountNumber) > Convert.ToInt64(y.strAccountNumber))
        {
          return 1;
        }
        if(Convert.ToInt64(x.strAccountNumber) == Convert.ToInt64(y.strAccountNumber))
        {
          return 0;
        }
      }
      return 0;
    }
  }

这让我从所有50k项目的15分钟缩短到了25秒。

这个问题似乎离题了,因为它属于Oops。是否可以将问题迁移到其他位置,或者我是否应该删除此项并在那里提问?我不知道,也许版主可以这样做。您可以从将ItemLimits存储在列表中开始,并在将其链接到匹配的数据记录后将其删除?Zache ItemLimits可以多次使用。他们必须呆在那里。我试着使用字典(我应该提到这一点),但出于某种原因,字典不允许我编辑
部分。还有lol@BlackMagicMethod。实际上,我已经找到了一种进行二进制搜索的方法,在我的机器上使用它可以从15分钟减少到25秒。如果你首先进行转换调用并将值存储在局部变量中,你就可以避免一些方法调用,我认为这会增加readability@Zache抢手货完成。
int index = Array.BinarySearch(itlaCreditLimits, new ItemLimits { strUserCode = dataset[i].User_UserCode, strAccountNumber = strUnEditedHomingAccountNo }, new ItemLimitsComparer());
if(index < 0)
{
  throw new Exception("Didn't find ItemLimit for UserCode = " + dataset.User_UserCode + " and account number " + strUnEditedHomingAccountNo);
}

ItemLimits ilItemLimit = itlaCreditLimits[index];