循环列表的更好方法

时间:2013-01-28 20:07:09

标签: c#

所以我有几个不同的列表,我正在尝试处理并合并到一个列表中。

下面是一段代码,如果有更好的方法,我想看看。 我之所以要问的是,其中一些列表相当大。我想看看是否有更有效的方法来做到这一点。

正如您所看到的,我正在遍历列表,我要做的第一件事就是检查列表中是否存在CompanyId。如果是,那么我在列表中找到我要处理的项目。

pList是我的进程名单。我将不同列表中的值添加到此列表中。

我想知道是否有“更好的方法”来完成存在和查找。

    boolean tstFind = false;
    foreach (parseAC item in pACList)
    {
        tstFind = pList.Exists(x => (x.CompanyId == item.key.ToString()));

        if (tstFind == true)
        {
            pItem = pList.Find(x => (x.CompanyId == item.key.ToString()));
            //Processing done here.  pItem gets updated here
            ...
         }

正如旁注,我将研究一种使用联接的方法,看看它是否更快。但我还没到那儿。上面的代码是我第一次解决这个问题,它似乎工作。但是,因为我有时间想看看是否还有更好的方法。

非常感谢任何输入。

时间发现:

  • 我当前的查找和存在代码大约需要 84分钟来遍历pACList中的5.5M项目。

  • 使用pList.firstOrDefault(x => x.CompanyId == item.key.ToString());需要 54分钟来遍历pACList

  • 中的5.5M项目

6 个答案:

答案 0 :(得分:3)

您可以使用FirstOrDefault检索项目,而不是两次搜索项目(第一次定义项目是否存在,第二次获取现有项目):

var tstFind = pList.FirstOrDefault(x => x.CompanyId == item.key.ToString());

if (tstFind != null)
{            
   //Processing done here.  pItem gets updated here        
}

答案 1 :(得分:3)

是的,使用哈希表使您的算法为O(n)而不是现在的O(n * m)。

var pListByCompanyId = pList.ToDictionary(x => x.CompanyId);
 foreach (parseAC item in pACList)
    {
        if (pListByCompanyId.ContainsKey(item.key.ToString()))
        {
            pItem = pListByCompanyId[item.key.ToString()];
            //Processing done here.  pItem gets updated here
            ...
         }

答案 2 :(得分:2)

您可以使用linq

遍历已过滤的列表
foreach (parseAC item in pACList.Where(i=>pList.Any(x => (x.CompanyId == i.key.ToString()))))
    {
            pItem = pList.Find(x => (x.CompanyId == item.key.ToString()));
            //Processing done here.  pItem gets updated here
            ...
    }

答案 3 :(得分:2)

使用此类操作的列表是O(MxN)(M是pACList的计数,N是pList的计数)。此外,您正在搜索pACList两次。要避免此问题,请按照@lazyberezovsky的建议使用pList.FirstOrDefault

但是,如果可能的话,我会避免使用列表。由您正在搜索的密钥编制索引的Dictionary将大大缩短查找时间。

答案 4 :(得分:2)

对列表中的每个项目进行线性搜索对于大型数据集效率不高。最好的方法是将密钥放入表或字典中,可以更有效地搜索,以允许您加入这两个表。您甚至不需要自己编写代码,您想要的是Join操作。您希望从每个序列中获取每个映射到相同键的所有项目对。

请执行以下方法,或将FooBar更改为相应的类型,并将其用作方法。

public static IEnumerable<Tuple<Bar, Foo>> Merge(IEnumerable<Bar> pACList
    , IEnumerable<Foo> pList)
{
    return pACList.Join(pList, item => item.Key.ToString()
        , item => item.CompanyID.ToString()
            , (a, b) => Tuple.Create(a, b));
}

您可以使用此调用的结果将两个项目合并在一起,因为它们将具有相同的密钥。

在内部,该方法将创建一个查找表,允许在实际进行搜索之前进行有效搜索。

答案 5 :(得分:1)

  1. 将pList转换为HashSet,然后查询pHashSet.Contains()。复杂度O(N)+ O(n)

  2. 在CompanyId上对pList进行排序并执行Array.BinarySearch()= O(N Log N)+ O(n * Log N)

  3. 如果Max公司ID不是非常大,只需创建和数组,其中公司ID为i的项目存在于第i个位置。没有比这更快的了。

  4. 其中N是pList的大小,n是pACList的大小