2013-04-07 71 views
1

我在VS 2010中使用C#4.0,試圖產生n個對象的交集或聯合。c#交叉點和聯盟不能正常工作

下正常工作:

IEnumerable<String> t1 = new List<string>() { "one", "two", "three" }; 
IEnumerable<String> t2 = new List<string>() { "three", "four", "five" }; 

List<String> tInt = t1.Intersect(t2).ToList<String>(); 
List<String> tUnion = t1.Union(t2).ToList<String>(); 
// this also works 
t1 = t1.Union(t2); 
// as does this (but not at the same time!) 
t1 = t1.Intersect(t2); 

但是,下列情況不。這些是代碼片段。

我的班級:

public class ICD10 
{ 
    public string ICD10Code { get; set; } 
    public string ICD10CodeSearchTitle { get; set; } 
} 

在下面:

IEnumerable<ICD10Codes> codes = Enumerable.Empty<ICD10Codes>(); 
IEnumerable<ICD10Codes> codesTemp; 
List<List<String>> terms; 
// I create terms here ---- 
// and then ... 
foreach (List<string> item in terms) 
{ 
    // the following line produces the correct results 
    codesTemp = dataContextCommonCodes.ICD10Codes.Where(e => item.Any(k => e.ICD10CodeSearchTitle.Contains(k))); 

    if (codes.Count() == 0) 
    { 
     codes = codesTemp; 
    } 
    else if (intersectionRequired) 
    { 
     codes = codes.Intersect(codesTemp, new ICD10Comparer()); 
    } 
    else 
    { 
     codes = codes.Union(codesTemp, new ICD10Comparer()); 
    }     
} 
return codes; 

上面永遠只能返回的最後一個項目的結果搜索。

我還添加了我自己的比較器,以防萬一,但是這並沒有區別:

public class ICD10Comparer : IEqualityComparer<ICD10Codes> 
{ 
    public bool Equals(ICD10Codes Code1, ICD10Codes Code2) 
    { 
     if (Code1.ICD10Code == Code2.ICD10Code) { return true; } 
     return false; 
    } 
    public int GetHashCode(ICD10Codes Code1) 
    { 
     return Code1.ICD10Code.GetHashCode(); 
    } 
} 

我確信我俯瞰明顯的東西 - 我看不出它是什麼!

+0

嘗試移動環路內codesTemp'的'的聲明,即'IEnumerable的 codesTemp = dataContextCommonCodes.ICD1 ...'。 – 2013-04-07 21:34:22

+0

感謝Joachim,很好的想法。可悲的是,這沒有什麼區別。 – 2013-04-07 21:39:07

+1

錯過了一件事情,您還需要''tmpItem = item;'並在'dataContextCommonCodes'Linq表達式中使用'tmpItem'而不是'item'。 – 2013-04-07 21:49:17

回答

3

此代碼:return codes;返回延遲枚舉。沒有執行任何查詢來填充該集合。有些查詢每次都通過循環來執行,以便進行計數。

由於關閉問題,此延遲執行是一個問題...在返回時,item被綁定到最後一個循環執行。

解決此通過強制查詢在每個循環執行,執行:

if (codes.Count() == 0) 
{ 
    codes = codesTemp.ToList(); 
} 
else if (intersectionRequired) 
{ 
    codes = codes.Intersect(codesTemp, new ICD10Comparer()).ToList(); 
} 
else 
{ 
    codes = codes.Union(codesTemp, new ICD10Comparer()).ToList(); 
} 
+1

+1是的,這是解釋,另一種方法是將'item'保存在循環內聲明的臨時變量中,所以它從不更新。 – 2013-04-07 22:00:38

+0

+1非常感謝大衛,只是工作,發現和其他所有的短語都非常感謝你 – 2013-04-07 22:04:55

1

如果您使用自己的比較器,則應該查看GetHashCode函數的正確實現。 linq運算符也使用這種比較。你可以看看這裏: http://msdn.microsoft.com/en-us/library/system.object.gethashcode(v=vs.80).aspx

你可以嘗試改變散列函數爲「返回0」,看看它是否是問題。 ICD10Code.GetHashCode如果它是一個類對象將返回可能不同的值

+0

對不起,這沒有做,但非常感謝評論 – 2013-04-07 22:06:06

0

您的問題肯定是不連接到IntersectUnion LINQ擴展方法。我剛剛測試了以下內容:

var t1 = new List<ICD10>() 
    { 
     new ICD10() { ICD10Code = "123" }, 
     new ICD10() { ICD10Code = "234" }, 
     new ICD10() { ICD10Code = "345" } 
    }; 
var t2 = new List<ICD10>() 
    { 
     new ICD10() { ICD10Code = "234" }, 
     new ICD10() { ICD10Code = "456" } 
    }; 

// returns list with just one element - the one with ICF10Code == "234" 
var results = t1.Intersect(t2, new ICD10Comparer()).ToList(); 

// return list with 4 elements 
var results2 = t1.Union(t2, new ICD10Comparer()).ToList(); 

使用您ICD10ICD10Comparer類的聲明。一切正常!您必須在自定義代碼中搜索錯誤,因爲LINQ工作得很好。

+0

他的表達式使用'item'在循環中不能很好地工作,因爲'item'在評估表達式之前發生了變化。 – 2013-04-07 21:58:12

+0

這是需要的ToList - thankd – 2013-04-07 22:05:35