2011-04-13 14 views
1

我有兩個泛型列表之間進行選擇:LINQ查詢的地方,我想運行幾個LINQ查詢,找出與泛型列表

  1. 是否有任何列出的名單B中發現的物品

  2. 是否所有名單在B名單中發現的物品

以下是名單:

var ListA = new List<long>() 
var ListB = new List<MyObject>() 

MyObject的定義爲:

public class MyObject 
    { 
    public long ItemId { get; set; }  
    // ... Other stuff... 
    } 

我試圖確定兩件事情(兩個查詢):1.執行任何利斯塔多頭的匹配數​​組listB任何MyObject.ItemId的? 2. ListA中的所有多頭都可以在ListB中找到嗎?

ListA和ListB可以有不同的長度。對於數字2,我需要ListB中的所有ListA項目,但反之亦然。我希望這是有道理的。

感謝,

斯科特

+0

我有點困惑的部分2.你是否想知道,如果在利斯塔的所有項目都包含在B的項目Id的或者是否需要包含在B的ItemId中的ListA值列表。稍有不同的查詢。你最後一句話是什麼讓我困惑。 – 2011-04-13 22:54:22

+0

我希望ListA中的每個long至少等於ListB中的一個MyObject.ItemId。 – Scott 2011-04-13 23:59:16

回答

6

首先,你只關心數組listB的ItemIds,所以:

var bIDs = ListB.Select(x => x.ItemId); 

要回答你的問題的第一部分,我會通過找到兩個列表(它們共享的所有項目的集合)的交集來解決這個問題。如果它至少有一個元素,那麼兩者之間會有重疊。

var sharedIds = ListA.Intersect(bIDs); 
if (sharedIds.Any()) 
    // list A contains at least one ItemID which ListB contains 

至於第二部分,你想看看列表A是列表B.搜索這個子集,堆棧溢出提出了clean solution

if (!ListA.Except(bIDs).Any()) 
    // yes, list A is a subset of list B 

這段代碼工作,因爲ListA.Except(bIDs)認定ListAbIDs沒有的元素。如果這是空的,則ListA不包含bIDs不包含的任何內容。因此,ListA中的所有內容也都在bIDs之內。

下面是一個例子:A = {1, 2}; B = {1, 2, 3}。 A是B的一個子集。A.Except(B)爲您提供了一個空集--B具有1和2,因此不能出現在結果列表中,並且B中沒有任何內容。因此,當A是B的子集時, A.Except(B).Any()給出錯誤,因爲結果中沒有元素;所以如果我們想要處理這種情況,我們顯然會否定它。爲了完整起見,如果我們交換A和B使得A不是B的子集:A = {1, 2, 3}; B = {1, 2},然後A.Except(B)給出{3}。它不能包含1或2,因爲B包含1和2.但B不包含3,所以A.Except(B)可以包含。由於{3}包含一個元素,因此它不是空的,所以A.Except(B).Any()爲真。否定的,如果A不是B的子集,那麼這是錯誤的。

我的解釋有點簡潔;如果你想進一步觀察事物(我建議你這樣做 - 一個小集合理論可以走很長的路),A.Except(B)是LINQ的名稱,用於設置差異或相對集合補碼。如果你有這種傾向,Wikibooks有一個體面的introduction來設定理論。

+0

+1比我要回答的要乾淨得多。 – Davy8 2011-04-13 22:59:08

+1

當然,這比需要的更復雜。 – flesh 2011-04-13 23:18:47

+0

@flesh:用'if'等等,它有點冗長;有什麼特別的你認爲可以簡化? – 2011-04-13 23:23:23

1
var value1 = 
(
    from itemA in ListA 
    where ListB.Any(itemB => itemB.ItemID == itemA) 
    select item 
).Count(); 

var value2 = value1 == ListA.Count(); 
0

爲了只是測試的條件下,假設你提取ItemIds列表爲listB

bool inListA = listA.Any(x => listB.Contains(x)); 

bool allInListB = listA.All(x => listB.Contains(x)); 

到位,測試無需提取單獨的列表,如果ItemIds

bool inListA = listA.Any(x => listB.Select(b => b.ItemId).Contains(x)); 

bool allInListB = listA.All(x => listB.Select(b => b.ItemId).Contains(x)); 
0

如果您需要回答所有這三個問題同時出現,那麼純LINQ解決方案很可能不是最優的,因爲每個查詢都需要執行相同的交集操作。做交集一次,然後用這個結果來回答你的三個問題:

var tempSet = new HashSet<long>(ListA); 
int uniqueAItemCount = tempSet.Count; 

// 2b. "I would need all of ListA's items found in ListB, but not vice-versa." 
tempSet.IntersectWith(ListB.Select(x => x.ItemId)); 
// tempSet now contains all items from ListA also found in ListB 
// we can use this result to answer the other two questions... 

// 1. "Do any of the longs in ListA match any of the MyObject.ItemId in ListB?" 
bool anyAFoundInB = tempSet.Count > 0; 

// 2a. "Can all of the longs in ListA be found in ListB?" 
bool allAFoundInB = tempSet.Count == uniqueAItemCount;