【问题标题】:Optimisation of LINQ query优化 LINQ 查询
【发布时间】:2019-04-15 10:34:41
【问题描述】:

有没有办法优化以下 LINQ 查询?当数组很大时效率不高。

public class Test
{
    public int Id { get; set; }
}
public static Test[] GetObjects(Test[] t, int[] ids)
{
    return t.Where(q => ids.Contains(q.Id)).ToArray();
}

【问题讨论】:

  • 您是实际上遇到性能问题还是只是猜测?我不认为你能比 O(n^2) 做得更好。你可以尝试将Tests 存储在字典中,使用它们的 ID 作为键,我猜...
  • ids 必须是一个数组吗?例如,如果您可以将ids 更改为HashSet<int>,效率会高得多。注意:我建议做类似var hash = new HashSet<int>(ids); inside 的方法 - 它应该在 outside 方法和相同的哈希值之后完成在数组将被使用的相同地方重用。或者,正如@Sweeper 所说:Dictionary<int, Test> 由 id 键入 - 再次重复使用,而不是每次都计算
  • 当您执行 ToArray() 时,您实际上是在与列表中的所有元素进行交互,即使您还不需要。您可以使用 IEnumerable 并且在您真正需要时进行查询。

标签: c# linq optimization query-optimization contains


【解决方案1】:

不返回数组。使用IEnumerable<Test>。这将极大地帮助内存使用,特别是如果您可以在整个程序的 API 表面中进一步传播该更改。任何你确实需要数组的地方,在函数调用之后调用.ToArray() 很容易,但同样......你做的越少,你就越有可能保存数组分配并复制。

public static IEnumerable<Test> GetObjects(IEnumerable<Test> t, IEnumerable<int> ids)
{
    return t.Where(q => ids.Contains(q.Id));
}

您可以通过将ids 变量转换为HashSet&lt;int&gt; 来进一步改进。这是否有帮助取决于集合的大小:

public static IEnumerable<Test> GetObjects(IEnumerable<Test> t, IEnumerable<int> ids)
{
    var idHash = new HashSet<int>(ids);
    return t.Where(q => idHash.Contains(q.Id));
}

甚至更好,因此您可能会重新使用哈希集或首先将ids 集合构建为哈希集:

public static IEnumerable<Test> GetObjects(IEnumerable<Test> t, HashSet<int> ids)
{
    return t.Where(q => idHash.Contains(q.Id));
}

在数据库世界中,我知道您也可以通过首先对ids 集合进行排序来优化它,但我不确定.Net 和 linq 现在是什么样子才能利用 IOrderedEnumerable。

【讨论】:

  • 和往常一样,对于性能优化问题,如果这有帮助,我很想看看之前和之后的数字。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-14
  • 1970-01-01
  • 2022-12-13
相关资源
最近更新 更多