2011-02-23 105 views
27

名單我有項目對象的列表:過濾使用LINQ

IEnumerable<Project> projects 

一個項目類作爲一個叫做標籤財產。這是一個INT []

我有一個稱爲filteredTags變量這也是一個INT []

因此,可以說我的過濾標籤變量是這樣的:

int[] filteredTags = new int[]{1, 3}; 

我想我過濾列表(項目)只返回都在過濾器中列出的標籤的項目(在此至少在標籤1和標籤3中屬於標籤屬性)。

我試圖用()和包含(),但似乎只如果我對一個值進行比較工作。我如何做這個比較列表與另一個列表,我需要在過濾列表中的所有項目匹配?

回答

37

編輯:更好的是,那樣做:

var filteredProjects = 
    projects.Where(p => filteredTags.All(tag => p.Tags.Contains(tag))); 

EDIT2:說實話,我不知道哪一個更好,所以如果性能並不重要,選擇你認爲一個更具可讀性。如果是這樣,你必須以某種方式進行基準測試。


大概Intersect是要走的路:

void Main() 
{ 
    var projects = new List<Project>(); 
    projects.Add(new Project { Name = "Project1", Tags = new int[] { 2, 5, 3, 1 } }); 
    projects.Add(new Project { Name = "Project2", Tags = new int[] { 1, 4, 7 } }); 
    projects.Add(new Project { Name = "Project3", Tags = new int[] { 1, 7, 12, 3 } }); 

    var filteredTags = new int []{ 1, 3 }; 
    var filteredProjects = projects.Where(p => p.Tags.Intersect(filteredTags).Count() == filteredTags.Length); 
} 


class Project { 
    public string Name; 
    public int[] Tags; 
} 

雖然這似乎起初有點難看。如果您不確定它們在列表中是否都是唯一的,則可以首先將Distinct應用於filteredTags,否則計數比較將無法按預期工作。

+0

我想你的'Intersect '方式比'更好'方法更清晰 – AakashM 2011-02-23 12:17:24

+0

@AakashM:我真的不知道,我現在正在努力決定它,我不喜歡'Count()',因爲它必須評估標籤'IEnumerable',但我很困惑我自己 – Dyppl 2011-02-23 12:21:02

2
var result = projects.Where(p => filtedTags.All(t => p.Tags.Contains(t))); 
+0

爲什麼?它不會允許標籤爲「1,2,3」的項目,還是我錯過了某些東西? – Dyppl 2011-02-23 12:07:03

+0

我不確定所有的都是正確的,因爲它需要工作,如果它有ATLEAST 1和3,但它可以有更多的。 。 。是不是所有()將驗證列表中的每個項目對1和3? – leora 2011-02-23 12:08:51

+0

我們可以稍微修改上面的代碼來達到預期的效果。 var result = projects.Where(p => filtedTags.All(t => p.Tags.Contains(t)) – 2011-02-23 12:17:09

1
var filtered = projects; 
foreach (var tag in filteredTags) { 
    filtered = filtered.Where(p => p.Tags.Contains(tag)) 
} 

這種方法的好處在於您可以逐步優化搜索結果。

2
var res = projects.Where(p => filteredTags.Except(p.Tags).Count() == 0); 
1

基於http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b

EqualAll是最能滿足您的需求的辦法。

public void Linq96() 
{ 
    var wordsA = new string[] { "cherry", "apple", "blueberry" }; 
    var wordsB = new string[] { "cherry", "apple", "blueberry" }; 

    bool match = wordsA.SequenceEqual(wordsB); 

    Console.WriteLine("The sequences match: {0}", match); 
} 
0

試試這個:

var filteredProjects = 
projects.Where(p => filteredTags.All(tag => p.Tags.Contains(tag))); 
+0

歡迎來到SO,請格式化您的代碼並寫一點描述。 – cSteusloff 2018-01-03 11:46:06