首页 > 解决方案 > 比较性能更好的 2 个列表?

问题描述

我有 2 个清单。一个是文件夹中所有文件的列表,另一个是数据库中的列表。我必须比较这些列表,我想知道是否有更好的方法来做到这一点,因为我认为性能会受到影响。这是我做的几种方法:

for(int i=0; i < docListFallback.Count; i++ )
{
    if (docListFallback[i].id == metadataItem.UniqueID.ToString())
    {
        if (docListFallback[i].modifiedDate < metadataItem.Geaendert)
        {
            isDocumentMissing = true;
            downloadFile = isDocumentMissing;
        }
        docListFallback.Remove(docListFallback[i]);
        break;
    }
}

和这个

for (int i = 0; i < docListModDate.Count; i++)
{
    if (docListModDate[i].id == metadataItem.UniqueID.ToString())
    {
        if (docListModDate[i].modifiedDate != metadataItem.Geaendert)
        {
           await _spManager.fileStorage.modifyDate(metadataItem.Geaendert, docListModDate[i].id);
        }
        docListModDate.Remove(docListModDate[i]);
        break;
    }
}

和这个

for(int i = 0; i < cleanupDocList.Count; i++)
{
    for(int j = 0; j < existingDocuments.Count; j++)
    {
        if(cleanupDocList[i].id == existingDocuments[j].UniqueID.ToString())
        {
            addToDelList = false;
            break;
        }
        else
        {
            addToDelList = true;
        }
    }
    if(addToDelList)
    {
        toDelete.Add(cleanupDocList[i].filename);
    }
}

foreach(string fileToDelete in toDelete)
{
    await _spManager.fileStorage.DeleteFileAsync(fileToDelete);
}

标签: c#performancefor-loopforeachuwp

解决方案


性能问题在这里:

for(int i = 0; i < cleanupDocList.Count; i++)
{
    for(int j = 0; j < existingDocuments.Count; j++)
    {
      ...
    }
}

这里发生的情况是,cleanupDocList您正在枚举existingDocuments. 这意味着如果两个列表中都有 N 个文件,则时间复杂度为O(N^2),这不是最佳的。

在这种情况下,您可以观察到您唯一感兴趣的是UniqueID,所以您可以做的是首先构建列表HashSet<string>中所有 id 的a existingDocuments,然后检查该项目是否存在于哈希集中。这要快得多,因为HashSet<>它是作为哈希表实现的,它具有恒定的查找平均时间复杂度 ( O(1)),这意味着我们总体上达到了O(N*1)=O(N)时间复杂度,这很重要,尤其是随着N增长。

代码如下所示:

var existingIds = new HashSet<string>(
        existingDocuments.Select(doc => doc.UniqueID.ToString()));

for(int i = 0; i < cleanupDocList.Count; i++)
{
    if (existingIds.Contains(cleanupDocList[i].id))
    { 
        toDelete.Add(cleanupDocList[i].filename);
    }
}

foreach(string fileToDelete in toDelete)
{
    await _spManager.fileStorage.DeleteFileAsync(fileToDelete);
}    

很棒的是,这种方法不仅提高了性能,而且同时大大简化了代码。让我们称之为双赢:-)!


推荐阅读