2011-09-28 33 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));