2011-09-28 58 views
3

讓我們假設我給Dictionary<int, List<int>>,我想用以下條件如何有效地修剪基於「爲子集」條件清單?

  • item應該從字典中刪除,如果存在在字典中的itemLarger != item這樣item.Value.Union(new[] { item.Key })itemLarger.Value.Union(new[] { itemLarger.Key })
  • 一個子集進行清理,

也就是說,字典中的每個項目都將通過將項目的關鍵字附加到項目的值而獲得的數字列表來表示,並且我想擺脫由某個其他項目的表示的子集表示的項目。

例子:

var testResult = new Dictionary<int, List<int>> 
{     
    { 2, new[] { 3, 4 }}, 
    { 3, new[] { 2, 4 }}, 
    { 1, new[] { 2, 3, 4 }}, 
    { 4, new[] { 2, 3 }} 
}; 

在這種情況下,留在列表中的唯一元素是{1, {2, 3, 4}}

我似乎無法找到一些優雅的方式做到這一點,因爲

  • GroupBy不允許我指定哪些元素特別應作爲關鍵的時候,我有兩個應該細分電子郵件
  • Distinct不允許我指定,如果兩個元素都沒有不同,這其中應保持在列表

當然這是一個平凡的方式是可行的。我想知道是否有一個很好的。

謝謝你的任何想法。

回答

2

我不認爲這將是你的意思是「微不足道」的方式非常不同,但這裏有一個LINQ的解決方案:

var sets = testResult 
.Select(x => new { Key = x.Key, Set = new HashSet<int>(x.Value.Concat(new[] { x.Key })) }) 
.ToList(); 
var res = sets.Where(s => sets.Any(x => x.Set.IsSupersetOf(s.Set) && x.Key != s.Key)); 
var keysToRemove = res.Select(x => x.Key); 
+0

+1:比我的方法好。它創建HashSets只有一次,使用內置的方法來確定的子集。 –

+0

編輯,以解決一些小錯誤:) – digEmAll

0

在我的解決方案我,如果這件檢查每個元素x在TestResult中是testResult中任何其他元素的子集。如果不是,則此元素在linq表達式中傳遞「where」過濾器。最後兩行是將結果從列表表示轉換爲字典表示。

var listResult = 
     (from x in testResult 
     where (from y in testResult 
       where !x.Value.Except(y.Value).Any() && x.Key != y.Key 
       select y).Count() == 0 
     select x).ToList(); 

    var dictionaryResult = new Dictionary<int, List<int>>(); 
    listResult.ForEach(x => dictionaryResult.Add(x.Key, x.Value)); 

編輯: 我們可以把它寫更短:

testResult = testResult.Where(x => 
    (from y in testResult 
    where !x.Value.Except(y.Value).Any() && x.Key != y.Key 
    select y).Count() == 0).ToDictionary(x => x.Key, x => x.Value); 
+0

請在你的答案正確格式的代碼,這樣就不必滾動那麼多。 –

+1

@丹尼爾。感謝您指出它,現在它已修復 –

0

這可能不是最有效的方式,但它很短,並且那種可讀性。

var test = new Dictionary<int, List<int>> 
{     
    { 2, new List<int> { 3, 4 }}, 
    { 3, new List<int> { 2, 4 }}, 
    { 1, new List<int> { 2, 3, 4 }}, 
    { 4, new List<int> { 2, 3 }} 
}; 

var res = test.Where(n => !test.Any(m => m.Key!=n.Key && n.Value.Intersect(m.Value).Count()==n.Value.Count));