繁体   English   中英

如何快速从第二组对象中获取第一组对象中不存在的对象?

[英]How can I take objects from the second set of objects which don't exist in the first set of objects in fast way?

我在两个数据库中都有记录。 那是第一个数据库中的实体:

public class PersonInDatabaseOne
{
    public string Name { get; set; }
    public string Surname { get; set; }
}

那是第二个数据库中的实体:

public class PersonInDatabaseTwo
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

我如何从第二个数据库中获取第一个数据库中不存在的记录(名字和姓氏必须与第一个数据库中的不同)。 现在我有类似的东西,但是非常慢,太慢了:

List<PersonInDatabaseOne> peopleInDatabaseOne = new List<PersonInDatabaseOne>();
// Hear I generate objects but in real I take it from database:
for (int i = 0; i < 100000; i++)
{
    peopleInDatabaseOne.Add(new PersonInDatabaseOne { Name = "aaa" + i, Surname = "aaa" + i });
}


List<PersonInDatabaseTwo> peopleInDatabaseTwo = new List<PersonInDatabaseTwo>();
// Hear I generate objects but in real I take it from database:
for (int i = 0; i < 10000; i++)
{
    peopleInDatabaseTwo.Add(new PersonInDatabaseTwo { FirstName = "aaa" + i, LastName = "aaa" + i });
}
for (int i = 0; i < 10000; i++)
{
    peopleInDatabaseTwo.Add(new PersonInDatabaseTwo { FirstName = "bbb" + i, LastName = "bbb" + i });
}


List<PersonInDatabaseTwo> peopleInDatabaseTwoWhichNotExistInDatabaseOne = new List<PersonInDatabaseTwo>();

// BELOW CODE IS VERY SLOW:
foreach (PersonInDatabaseTwo personInDatabaseTwo in peopleInDatabaseTwo)
{
    if (!peopleInDatabaseOne.Any(x => x.Name == personInDatabaseTwo.FirstName && x.Surname == personInDatabaseTwo.LastName))
    {
        peopleInDatabaseTwoWhichNotExistInDatabaseOne.Add(personInDatabaseTwo);
    }
};

最快的方法取决于实体的数量以及您已经拥有的索引。

  • 如果有几个实体,那么您已经拥有的实体会获得更好的性能,因为对一个小集合进行多次扫描所需的时间少于创建HashSet对象的时间。

  • 如果所有实体都适合内存 ,最好的方法是从它们中构建HashSet ,并使用Except ,@ alex.feigin对此进行了详细介绍。

  • 如果您负担不起加载内存中的所有实体,则需要根据比较键将它们划分为大块,然后将其加载到内存中,然后重复应用HashSet方法。 请注意,批量不能基于记录数,而是基于比较键。 例如,加载名称以'A' ,然后以'B'开头的所有实体。

  • 如果您已经在其中一个数据库中的比较键上为数据库创建了索引(例如您的LastName ,例如FirstNameLastName ),则可以从数据库中检索排序列表。 这将帮助您在排序列表上进行二进制搜索( http://en.wikipedia.org/wiki/Binary_search_algorithm )以进行比较。 参见https://msdn.microsoft.com/zh-cn/library/w4e7fxsh(v=vs.110).aspx

  • 如果已经在两个数据库的比较键上的数据库上都有索引,则可以在O(n)中以可扩展的方式(任意数量的记录)进行操作。 您只需要遍历两个列表并只查找一次差异。 有关更多详细信息,请参见https://stackoverflow.com/a/161535/187996

编辑:关于评论-使用真实模型和字典而不是简单的集合:

尝试将列表散列到Dictionary中,以容纳人员对象,作为键-尝试使用元组而不是name1 == name2 && lname1 == lname2。

然后可能看起来像这样:

// Some people1 and people2 lists of models already exist:
var sw = Stopwatch.StartNew();
var removeThese = people1.Select(x=>Tuple.Create(x.FirstName,x.LastName));
var dic2 = people2.ToDictionary(x=>Tuple.Create(x.Name,x.Surname),x=>x);
var result =  dic2.Keys.Except(removeThese).Select(x=>dic2[x]).ToList();
Console.WriteLine(sw.Elapsed);

我希望这有帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM