gpt4 book ai didi

c# - 此 LINQ 代码是否对原始数据执行多次查找?

转载 作者:太空狗 更新时间:2023-10-29 17:46:44 24 4
gpt4 key购买 nike

我们在一段使用 LINQ 的代码中遇到了一个轻微的性能问题,它引发了一个关于 LINQ 在查找方面如何工作的问题

我的问题是这样的(请注意,我已经更改了所有代码,所以这是代码的指示性示例,而不是真实场景):

给定

public class Person {
int ID;
string Name;
DateTime Birthday;
int OrganisationID;
}

如果我有一个包含 100k 个 Person 对象的列表,然后是一个日期列表,比如 1000 个,我运行了这段代码:

var personBirthdays = from Person p in personList
where p.OrganisationID = 123
select p.Birthday;

foreach (DateTime d in dateList)
{
if (personBirthdays.Contains(d))
Console.WriteLine(string.Format("Date: {0} has a Birthday", d.ToShortDateString()));
}

生成的代码将是以下内容的迭代:

100k(查找组织ID为123的用户需要执行的循环)
乘以
1000(列表中的日期数量)
乘以
x(组织 ID 为 123 的用户数量,用于检查日期)

这是很多迭代!

如果我将 personBirthdays 的代码更改为:

List<DateTime> personBirthdays = 
(from Person p in personList
where p.OrganisationID = 123
select p.Birthday).ToList();

这应该删除 100k 作为倍数,只做一次吗?

所以你会得到 100k + (1000 * x) 而不是 (100k * 1000 * x)。

问题是这看起来太简单了,我确信 LINQ 在某个地方做了一些聪明的事情,这应该意味着这不会发生。

如果没有人回答,我会进行一些测试并报告。

清晰度更新:我们不考虑数据库查找,personList 对象是内存列表对象。这都是 LINQ-to-Objects。

最佳答案

This should remove the 10k as a multiple by, and just do it once?

这意味着不是将 personList 迭代 10 万次,而是为每次迭代执行 whereselect 操作 您将迭代生成的 List 100k 次,并且 whereselect 操作只会在基础数据源一次。

The question is that this seems too easy, and I'm sure the LINQ is doing something clever somewhere that should mean that this doesn't happen.

不,你的第一个查询只是一些你不应该使用 LINQ 做的事情,如果你计划多次迭代它们,你应该获取查询的结果并将它们放入数据结构中(这就是你改变了)。

您可以通过使用适当的数据结构进一步改进此查询。在 List 上搜索效率很低,因为它需要进行线性搜索。最好使用 HashSet 来存储查询结果。 HashSet 在平均情况下的搜索速度为 O(1),而 List 的搜索时间为 O(n)。

var dates = new HashSet<DateTime>(from Person p in personList
where p.OrganisationID = 123
select p.Birthday);

foreach (DateTime d in dateList.Where(date => dates.Contains(date)))
{
Console.WriteLine(string.Format("Date: {0} has a Birthday", d.ToShortDateString()));
}

关于c# - 此 LINQ 代码是否对原始数据执行多次查找?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13823368/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com