2009-03-03 14 views
2

VeriB'deki dataA öğelerinin alt kümesini elde etmeye çalışıyorum ve farklı özellik değerlerine sahip olmak c. A ve b özellikleri bir indeks olarak kullanılabilir, bu yüzden sadece yararlı çiftleri filtrelemeye çalıştım ve farklı bir c değerine sahip olup olmadığını kontrol etmeyi denedim.Öğelerin bir alt kümesini, kısmen farklılık gösteren iki veri kümesinde nasıl bulurum?

Bu, geldiğim linq ifadesidir ve işe yarıyor, ancak bu alt kümeyi bulmanın daha iyi/daha hızlı bir yolu olmalı gibi görünüyor.

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

Bu bir harekettir, ancak neden .Intersect() çalışmıyor? http://msdn.microsoft.com/en-us/library/system.linq.queryable.intersect.aspx – Portman

+0

Intersect çiftleri iade etmiyor –

cevap

2

Daha hızlı? Sahip olduğunuz şey O (n^2). İlk listedeki her öğe, ikinci listedeki öğeleri tamamen yineleyecektir. Bu birleştirmede gereksiz yinelemeyi kaldırmanız gerekir. Bunu yapmanın bir yolu, maçlar için O (1) aramaları yapmak için başka bir yapı kullanmaktır. a, b çiftleri her listesindeki benzersiz olup olmadığını Burada basitleştirilmiş versiyonu

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}) 
    ) 
); 

:

İşte bazı denenmemiş (kontrolsüz) kod. David B tarafından sağlanan cevap dayanarak

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

, sonunda onun yöntemin biraz değiştirilmiş bir sürümü üzerinde yerleşti. Farklılıklar küçük olsa da, bunu paylaşmayı düşündüğümde, öncelikle (benim gibi) ifade edici sözdizimini tercih eden bir versiyonu göstereceğim.

Ayrıca, gruplama yerine, yapının basitleştirilmesi için anonim bir anahtar/değer çifti kullanmaya karar verdim.

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; 
+0

Holy Moses! :) çaba için +1 + – leppie

+0

evet ... biraz çirkin, ama çok daha hızlı bir heck ... – chills42

+0

Gratz, her şey yolunda gitti. Her listedeki a, b çiftlerinin benzersiz olduğunu mu görüyorum? Bunu bilseydim daha basit bir cevap yazabilirdim. –

İlgili konular