2015-11-03 44 views
2

我有一个List<Organisation>组织。Linq通过比较两个int类型的列表来选择对象

每个Organisation有一个属性List<int> Categories

我也有一个单独的List<int> DisplayCategories

我想创建一个新的名为List<Organisation>DisplayOrganisations

DisplayOrganisations将包含Organisation的谁的Categories出现在我的List<int> DisplayCategories

如何使用linq或lambda来实现这个功能?

以下是不正确的:

DisplayOrganisations = (from o in Organisations 
         where o.Categories.Intersect(DisplayCategories.CategoryIds) 
         select o).ToList(); 

我得到一个错误:

Cannot implicitly convert type 'System.Collections.Generic.IEnumerable' to 'bool'

我认为,这是因为我选择机构是谁的分类的子列表需要被比作一个单独列表DisplayCategories。

任何想法?

+0

请不要使用secon d的方法在我的答案中。使用第一个。由于其经过验证的Intersect更适合大型收藏。再次看到答案。 –

+0

@ M.kazemAkhgary谢谢你,我已经修改我的代码来使用相交,就像你的更新, – fourbeatcoder

回答

3

当然相交不会给布尔值。你可能要检查是否有任何元素存在于它使用Any

DisplayOrganisations = Organisations 
         .Where(o => o.Categories.Intersect(DisplayCategories.CategoryIds) 
               .Any()).ToList(); 

或更好的方法。 DisplayOrganisations = Organisations.Where(o => o.Categories .Any(xDisplayCategories.CategoryIds.Contains))。ToList();

正如你可以相交使用HashSet比第二种方法更快,因为拥有的Hashset用于添加并删除项目的O(1)时间复杂度的图片中看到。所以一般Intersect是O(n+m)。但使用AnyContains的第二种方法的时间复杂度为O(n^2),可能会变得更慢。感谢Dmitry Dovgopoly

enter image description here

+0

我猜测相交需要比线性搜索更多的时间。即时通讯不知道什么是时间复杂性,但我很欣赏,如果你分享你的知识,所以我会修复我的答案,也学习一些东西;)@DmitryDovgopoly –

+1

其实第二种方法更糟。相交使用'hashset'并且很快。 “任何”都适用于所有元素,复杂度为n * n。您可以通过从xDisplayCategories.CategoryIds'创建一个哈希集来优化它。 –

+0

感谢您的信息!非常感激。我不知道相交使用哈希集。所以我认为这可能是找出两个列表至少包含一个相同项目的最快方法。 (忽略微观优化)@DmitryDovgopoly –

2

如果您只需要那些所有元素都在CategoryIds列表,你可以使用Except()Any()方法混合组织:

var DisplayOrganisations = Organisations.Where(o => 
         !o.Categories.Except(DisplayCategories.CategoryIds).Any()).ToList(); 

如果你只是想确认至少有您可以使用的ID列表中的一个ID .Any方法:

var DisplayOrganisations = Organisations.Where(o => o.Categories 
             .Any(DisplayCategories.CategoryIds.Contains)).ToList();