2011-07-30 46 views
2

如何使用基于具有非唯一值的属性的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以优化性能。但是那些值不是唯一的情况呢?

+0

根据'标题'排序的二叉搜索树可能(如果这是您需要查找的唯一属性) – Magnus

+0

您的最后一个查询不会编译。你的意思是'string.IsNullOrEmpty(c.Title)'? – svick

+0

@svick:已修改。谢谢。 –

回答

2

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

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

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

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

2

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

有一个叫i4o的库,显然可以解决你的问题:

http://i4o.codeplex.com/

从他们的网站:

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

i4o的工作原理是让开发人员指定的 IndexSpecification任何类,然后使用 IndexableCollection实现这个类的一个集合, 将使用索引规范,而不是顺序查找,当 做LINQ操作可以从索引中受益。

还有以下提供了如何使用i4o的一个例子:

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

长话短说,你需要:

  1. 添加[可转位()]属性到你的“标题“属性
  2. 使用IndexableCollection <产品>作为您的数据源。
  3. 从这一点来看,任何使用索引字段的linq查询都将使用该索引而不是执行顺序搜索,从而导致使用该索引的查询的magnituide性能增加顺序。
+0

+1不错。你对这个图书馆有很好的经验吗? – sgtz

+0

我还没有在生产中使用它,但期待这样做。 –