2013-02-20 52 views
2

我有一種情況,我已經生成了一些包含整數值的列表。但是,這些列表的數量僅爲,僅在運行時已知,並且結果列表中存在的整數必須存在於所有列表中。有沒有將所有這些列表連接到單個列表的方法?在linq中加入未知的列表數量

List<int> l1 = {1, 2, 3, 4}; 
List<int> l2 = {2, 3, 5, 7, 9}; 
List<int> l3 = {3, 9, 10}; 
List<int> ln = {....}; 

結果列表應該如下

List<int> r = {3}; 

這可能與LINQ或任何其它方法嗎?

+3

以陣列,列表或類似的名單?你已經在編譯時顯示它們被定義了,它不符合你的問題... – 2013-02-20 16:27:06

+0

另外,它是否必須在LINQ中完成?這是你試圖避免記錄被從數據庫中拉出來的地方,還是在本地系統的內存中處理結果? – 2013-02-20 16:28:52

+0

請參閱:http://stackoverflow.com/questions/3191810/linq-intersect-multiple-lists-some-empty對於類似的問題。 – dugas 2013-02-20 16:32:14

回答

1
// lists is a sequence of all lists from l1 to ln 
if (!lists.Any()) 
    return new List<int>(); 

IEnumerable<int> r = lists.First(); 

foreach(List<int> list in lists.Skip(1))  
    r = r.Intersect(list); 

return r.ToList(); 
+0

這不回答(不清楚),但是這些列表的數量只在運行時才知道「問題的一部分 – ken2k 2013-02-20 16:34:01

+0

@ ken2k那是因爲不清楚這些列表是如何檢索的。我相信OP可以列舉他們,但我會在問題 – 2013-02-20 16:37:15

4

我假設你有一個List<List<int>>保存可變數量的List<int>

您可以用第二個列表intersect第一列表

var intersection = listOfLists[0].Intersect(listOfLists[1]); 

,然後相交與第三列表

intersection = intersection.Intersect(listOfLists[2]); 

,並依此類推,直至intersection持有的所有列表的交集的結果。

intersection = intersection.Intersect(listOfLists[listOfLists.Count - 1]); 

使用for循環:

​​

使用foreach環(如圖@lazyberezovsky):

IEnumerable<int> intersection = listOfLists.First(); 

foreach (List<int> list in listOfLists.Skip(1)) 
{ 
    intersection = intersection.Intersect(list); 
} 

使用Enumerable.Aggregate

var intersection = listOfLists.Aggregate(Enumerable.Intersect); 

如果順序並不重要,那麼你也可以使用一個HashSet<T>你與第一列表填充和intersect with用剩下的列表(如圖@Servy)。

var intersection = new HashSet<int>(listOfLists.First()); 

foreach (List<int> list in listOfLists.Skip(1)) 
{ 
    intersection.IntersectWith(list); 
} 
+0

上添加註釋雖然全部爲真,但這並不回答(不清楚),但是這些列表的數量僅在運行時已知「問題的一部分 – ken2k 2013-02-20 16:30:52

+0

將循環變量保留在循環之外應該相當容易,那麼你可以(大概)遍歷列表 - 編輯:根據lazyberezovsky的回答 – penguat 2013-02-20 16:32:04

+2

我喜歡'Aggregate'版本。 – Rawling 2013-02-20 16:54:34

0

這裏有一個簡單的方法來獲取集合的集合的交集:

public static IEnumerable<T> Intersect<T>(IEnumerable<IEnumerable<T>> sequences) 
{ 
    using (var iterator = sequences.GetEnumerator()) 
    { 
     if (!iterator.MoveNext()) 
      return Enumerable.Empty<T>(); 

     HashSet<T> intersection = new HashSet<T>(iterator.Current); 

     while (iterator.MoveNext()) 
      intersection.IntersectWith(iterator.Current); 

     return intersection; 
    } 
} 

這裏的想法是把所有的物品爲一組,然後交叉是與每個序列反過來。我們可以使用簡單的LINQ來減少很多代碼,但是這將會從每個交集的結果中填充一個新的HashSet,而不是重複使用一個單獨的交集,所以儘管看起來非常優雅,但它會有更高的開銷。

這裏是少高性能但更優雅的解決方案:

public static IEnumerable<T> Intersect<T>(IEnumerable<IEnumerable<T>> sequences) 
{ 
    return sequences.Aggregate(Enumerable.Intersect); 
}