如何在字典中查找重复对?

时间:2010-11-24 16:20:02

标签: c# .net algorithm dictionary

我想计算TCC指标:

  

紧密级别凝聚力(TCC)   衡量人数的比例   方法对直接连接   类NDC(C)和类中的可见方法   最大可能方法的数量   两对之间的连接   NP(C)类的可见方法。二   可见方法是直接的   连接,如果他们正在访问   该类的相同实例变量。   n是可见方法的数量   导致:

NP(C) = (n(n-1))/2

TCC(C) = NDC(C) / NP(C)

所以我编写了一个方法来解析我要检查的类中的所有方法。此方法存储该类中的所有方法以及它们在字典中使用的字段,如下所示:

Dictionary<MethodDefinition, IList<FieldReference>> references = new Dictionary<MethodDefinition, IList<FieldReference>>();

现在,如何遍历此词典以检查上述情况?如果我理解正确的话,我必须找到使用同一组字段的这两对方法?那我怎么能以最好的方式做到这一点呢?我想我必须遍历字典并查看IList是否包含相同的集合? (甚至不是以相同的顺序)?

任何想法?

我的代码如下,但它无法正常工作:

class TCC
    {

        public static int calculate(TypeDefinition type)
        {
            int count = 0;


            Dictionary<MethodDefinition, HashSet<FieldReference>> references = new Dictionary<MethodDefinition, HashSet<FieldReference>>();

            foreach (MethodDefinition method in type.Methods)
            {
                if (method.IsPublic)
                {
                    references.Add(method, calculateReferences(method));
                }
            }

            for (int i = 0; i < references.Keys.Count; i++)
            {
                HashSet<FieldReference> list = new HashSet<FieldReference>();
                references.TryGetValue(references.Keys.ElementAt(i), out list);

                if (isPair(references, list)) {
                    count++;
                }

            }

            if (count > 0)
            {
                count = count / 2;
            }

            return count;
        }

        private static bool isPair(Dictionary<MethodDefinition, HashSet<FieldReference>> references, HashSet<FieldReference> compare)
        {
             for (int j = 0; j < references.Keys.Count; j++)
                {
                    HashSet<FieldReference> compareList = new HashSet<FieldReference>();
                    references.TryGetValue(references.Keys.ElementAt(j), out compareList);

                    for (int i = 0; i < compare.Count; i++)
                    {
                        if (containsAllElements(compareList, compare)) {
                            return true;
                        }
                    }
                }

             return false;
        }

        private static bool containsAllElements(HashSet<FieldReference> compareList, HashSet<FieldReference> compare)
        {
            for (int i = 0; i < compare.Count; i++)
            {
                if (!compareList.Contains(compare.ElementAt(i)))
                {
                    return false;
                }
            }
            return true;
        }

        private static HashSet<FieldReference> calculateReferences(MethodDefinition method)
        {
            HashSet<FieldReference> references = new HashSet<FieldReference>();
            foreach (Instruction instruction in method.Body.Instructions)
            {
                if (instruction.OpCode == OpCodes.Ldfld)
                {
                    FieldReference field = instruction.Operand as FieldReference;
                    if (field != null)
                    {
                        references.Add(field);
                    }
                }
            }

            return references;
        }
    }

4 个答案:

答案 0 :(得分:2)

好吧,如果你不介意另外一本字典,我们可以用一把大锤子打这个东西 简单地说,如果我们想象一个字典,其中ordered_set(字段引用)是键,而我们保留每个键的值列表....不用说这不是最聪明的方法,但它是快速,简单,并使用您已熟悉的数据结构。

EG:
hashset< hashset < FieldReference >, Ilist< methods >> Favorite_delicatessen

Build ReferenceSet for method
Look up ReferenceSet in Favorite_Delicatessen
If there:
Add method to method list
Else:
Add Referenceset,method pair

因此你的方法列表是共享相同状态签名的方法列表,如果你让我用一个术语。

答案 1 :(得分:1)

您可以使用ContainsValue检查重复项吗?根据您描述的内容,如果相同,则只显示重复项。

答案 2 :(得分:1)

由于您没有告诉我们如何判断两个FieldReference是否重复,我将使用默认值。

LINQ版本:

int duplicated = references.SelectMany( p => p.Value )
                           .GroupBy(x => x)
                           .Where(g => g.Count() > 1)
                           .Count();

答案 3 :(得分:1)

如何获取字符,其中键是重复项,并且值是原始字典中包含副本的键列表:

var dupes = references
    .SelectMany(k => k.Value)
    .GroupBy(v => v)
    .Where(g => g.Count() > 1)
    .ToDictionary(i => i.Key, i => references
        .Where(f => f.Value.Contains(i.Key))
        .Select(o => o.Key));