根据属性快速选择集合中的元素

时间:2011-07-30 11:59:28

标签: c# linq optimization query-optimization

如何使用基于具有非唯一值的属性的lambda表达式来存储大型集合的多个值,以便能够快速找到它们?

示例案例(未针对性能进行优化):

class Product
{
    public string Title { get; set; }
    public int Price { get; set; }
    public string Description { get; set; }
}

IList<Product> products = this.LoadProducts();

var q1 = products.Where(c => c.Title == "Hello"); // 1 product.
var q2 = products.Where(c => c.Title == "Sample"); // 5 products.
var q3 = products.Where(c => string.IsNullOrEmpty(c.Title)); // 12 345 products.

如果标题是唯一的,则可以使用IDictionaryHashSet轻松优化效果。但是值不是唯一的情况怎么样?

2 个答案:

答案 0 :(得分:2)

您需要的是能够在LINQ中运行索引查询。 (和我们在SQL中一样)

有一个名为i4o的库,显然可以解决您的问题:

http://i4o.codeplex.com/

来自他们的网站:

  

i4o(对象索引)是第一个扩展LINQ的类库   允许您在对象上放置索引。使用i4o,速度   LINQ操作通常比没有LINQ操作快一千倍   i4o的。

     

i4o允许开发人员指定一个   任何类的IndexSpecification,然后使用   IndexableCollection实现该类的集合   将使用索引规范,而不是顺序搜索   执行可以从索引中受益的LINQ操作。

以下提供了如何使用i4o的示例:

http://www.hookedonlinq.com/i4o.ashx

缩短你需要:

  1. 将[Indexable()]属性添加到“标题”属性
  2. 使用IndexableCollection&lt;产品&gt;作为您的数据源。
  3. 从这一点来看,任何使用可索引字段的linq查询都将使用索引而不是进行顺序搜索,从而导致使用索引的查询的magnituide性能提升顺序。

答案 1 :(得分:2)

最简单的解决方案是使用Product的集合字典。最简单的是使用

var products = this.LoadProducts().ToLookup(p => p.Title);

var example1 = products["Hello"]; // 1 product
var example2 = products["Sample"]; // 5 products

你的第三个例子有点困难,但你可以使用ApplyResultSelector()