首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何比较和更新包含大量项目的2个列表?

如何比较和更新包含大量项目的2个列表?
EN

Stack Overflow用户
提问于 2019-06-22 23:23:53
回答 5查看 74关注 0票数 0

注意:使用LINQ join解决了这个问题。

我需要比较源列表中的列表值,如果它存在于目标列表中,如果是,则将其保存到第三个列表中。

我写的代码确实可以工作,但它花费了很多时间,因为我的Source List有30k个项目,并且它将每个项目的值与1500万的目标列表进行比较,这需要很多时间。因为它每次都会遍历整个列表(30k *1500万次)

请看代码,它显然不是最优的,但可以完成工作。

        // The below code will generate the lists from CSV file
        The lists are below for sample

        **Source List**
        FileId  FilePath      FileChecksum
        1       somepath A    check1
        2       somepath AA   check2
        3       somepath AAB  check3
        4       somepath B    check4
        5       somepath BB   check5

        **Destination List**

        StepId  StatusID  JobId ProjectId FileId     FilePath
        5        6         4    2091      577206853  somepath A
        5        6         4    2092      577206853  somepath AA
        5        6         4    2093      577206853  somepath AAA
        5        6         4    2094      577206853  somepath AB
        5        6         4    2095      577206853  somepath A
        5        6         4    2096      577206853  somepath B
        5        6         4    2097      577206853  somepath BB

        List<Source> SourceList = File.ReadAllLines(@"D:\source.csv").Skip(1).Select(v => Source.SourceFromCSv(v)).ToList();

        List<Destination> DestinationList = File.ReadAllLines(@"D:\Destination.csv").Skip(1).Select(d => Destination.FromDestinationCSV(d)).ToList();

        //This will compare and create a new list
        var result1 =
            from s in SourceList
            from d in DestinationList
            where (d.FilePath.ToLower() == s.FilePath.ToLower())
             select (d.StepId + "," + d.StatusId + "," + d.JobId + "," + 
             d.ProjectId + "," + d.FileId + "," + d.FilePath + "," + 
             s.FileChecksum);



             Expected Result:
             StepId StatusID  JobId ProjectId FileId    FilePath      FileChecksum
             5       6         4    2091      577206853 somepath A    check1
             5       6         4    2092      577206853 somepath AA   check2
             5       6         4    2095      577206853 somepath A    check1
             5       6         4    2096      577206853 somepath B    check4
             5       6         4    2097      577206853 somepath BB   check5
EN

回答 5

Stack Overflow用户

发布于 2019-06-23 00:08:10

您可以对两个列表进行排序,然后逐行比较。算法复杂度为O(n+n n+n)。

将第一行数据A与第一行数据B进行比较,然后增加“较大”行上指针的索引。如果数据A有8,数据B有7和9,那么一旦达到9,就会知道数据B中不存在8。

你应该从最大可能的索引开始比较。这样,如果列表确实是一个子列表,就可以快速终止。

票数 3
EN

Stack Overflow用户

发布于 2019-06-22 23:53:52

你可以反过来做这件事。您可以遍历您的3000万个条目,而不是从30k个源条目中挑选一个。如果您找到了全部30k个条目,或者在最坏的情况下,在3000万个条目之后停止,则可以停止。这仍然比30K*15M要好。

票数 1
EN

Stack Overflow用户

发布于 2019-06-22 23:56:02

是的,如果你不需要它的所有特性都是一个列表,那么将基类型设为HashSet<T>将会显著提高查找效率。您的自定义类型可能需要实现适当的GetHashCode()函数来进一步提高查找速度。

请参见:

不要调用new HashSet(query.ToList()),而是在实例化列表query.ToHashSet()时直接转换为哈希集,可选地传入一个相等比较器,如下所示:

除了自定义GetHashCode实现之外,您还可以实现自定义IEqualityComparer来处理特定情况,如您的情况,其中特定字段构成相等规则。Visual Studio和Resharper现在提供了一个built-in refactor to generate a good implementation of GetHashCode and Equals

请参见:

然后,您可以使用IntersectWith在单个调用中获取这两个集合中的所有项目:

请参见:

创建一个可以同时转换SourceDestination的特殊对象,或者为它们提供相同的基类,就可以实现这一点。

您也可以使用IDictionary<Key, Value>并将密钥设置为Item.FilePath.ToLower(),上述原则同样适用。这将允许运行时使用字符串的GetHashCode检查该项目是否存在于其他列表中,该字符串在默认情况下是高度优化的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56716705

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档