2009-03-03 34 views
2

我想獲得dataA中dataA中的項目子集,並擁有不同的屬性值c。屬性a和b可以用作索引,所以我試圖只篩選出有用的對,然後檢查它們是否具有不同的c值。如何找到部分不同的兩組數據中的項目子集?

這是我想出來的linq表達式,它確實有效,但似乎必須有更好/更快的方式來找到這個子集。

var itemsInBoth = from item in dataA 
        from item2 in dataB 
        where item.a == item2.a && item.b == item2.b 
         select new 
         { 
          first= item, 
          second = item2 
         }; 
var haveDifferentC = from item in itemsInBoth 
        where item.first.c != item.second.c 
        select item.first; 
+0

這是一個驅動器,但爲什麼不.Intersect()的工作? http://msdn.microsoft.com/en-us/library/system.linq.queryable.intersect.aspx – Portman 2009-03-03 14:41:27

+0

相交不返回對 – 2009-03-03 15:01:34

回答

2

更快?你在那裏有O(n^2)。第一個列表中的每個項目將完全迭代第二個列表中的項目。您需要刪除該連接中的冗餘迭代。一種方法是使用另一個結構來執行O(1)查找匹配。

下面是一些未經測試(未選中),代碼:

var dictionaryA = dataA 
    .GroupBy(item => new {a = item.a, b = item.b}) 
    .ToDictionary(g => g.Key, g => g.ToList()); 

var dictionaryB = dataB 
    .GroupBy(item => new {a = item.a, b = item.b}) 
    .ToDictionary(g => g.Key, g => g.ToList()); 

var results = dictionaryA 
    .Where(g1 => dictionaryB.ContainsKey(g1.Key)) 
    .Select(g1 => new {g1 = g1, g2 = dictionaryB[g1.Key]}) 
    .SelectMany(pair => 
    pair.g1.SelectMany(item1 => 
     pair.g2 
     .Where(item2 => item2.c != item1.c) 
     .Select(item2 => new {item1, item2}) 
    ) 
); 

下面是一個簡化版本,如果A,B對是在每個列表中是唯一的。

var dictionaryA = dataA 
    .ToDictionary(item => new {a = item.a, b = item.b}, item => item); 

var dictionaryB = dataB 
    .ToDictionary(item => new {a = item.a, b = item.b}, item => item); 

var results = dictionaryA 
    .Where(e1 => dictionaryB.ContainsKey(e1.Key)) 
    .Select(e1 => new {i1 = e1.Value, i2 = dictionaryB[e1.Key]}) 
    .Where(pair => pair.i1.c != pair.i2.c); 
3

根據David B提供的答案,我最終確定了他的方法的一個稍微修改後的版本。儘管差異很小,但我認爲我會分享這些,主要是爲了展示那些喜歡錶達式語法的人(比如我)。

此外,我決定使用匿名鍵/值對來簡化結構,而不是分組。

var dictA = (from item in dataA 
      select new 
      { 
       key = CreateIndexValue(item.a, item.b), 
       value = item 
      }).ToDictionary(kv => kv.key, kv => kv.value); 
var dictB = (from item in dataB 
      select new 
      { 
       key = CreateIndexValue(item.a, item.b), 
       value = item 
      }).ToDictionary(kv => kv.key, kv => kv.value); 
var filesInBoth = from item in dictA 
        where dictB.ContainsKey(item.Key) 
        select new 
        { 
         itemA = dictA[item.Key], 
         itemB = dictB[item.Key] 
        }; 
var differentSize = from item in filesInBoth 
        where item.itemA.c!= item.itemB.c 
        select item.itemA; 
相關問題