Как найти повторяющиеся пары в словаре? - PullRequest
2 голосов
/ 24 ноября 2010

Я хотел бы рассчитать метрику TCC:

Tight Class Cohesion (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 тот же набор?(даже не в том же порядке)?

Любые идеи oder`?

Мой код следующий, но он не работает правильно:

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 ]

2 голосов
/ 24 ноября 2010

Что ж, если вы не возражаете против сохранения другого словаря, мы можем ударить по нему большим молотком.
Проще говоря, если мы представляем словарь, в котором вместо этого указывается order_set (field-reference), и мы храним список значений для каждого ключа .... Нет необходимости говорить, что это не самый умный подход, но быстрый, простой и использует структуры данных, с которыми вы уже знакомы.

EG:
hashset< hashset < FieldReference >, Ilist< methods >> Favorite_delicatessen </p> <p>Build ReferenceSet for method<br> Look up ReferenceSet in Favorite_Delicatessen<br> If there:<br> Add method to method list<br> Else:<br> Add Referenceset,method pair

И ваш список методов, таким образом, представляет собой список методов, которые используют одну и ту же сигнатуру состояния, если вы позволите мне поменять термин.

1 голос
/ 25 ноября 2010

Как насчет получения словаря, ключом которого является дубликат, а значением является список ключей из исходного словаря, которые содержат дубликат:

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));
1 голос
/ 24 ноября 2010

Поскольку вы не сказали нам, как мы можем определить, что два FieldReference дублированы, я буду использовать значение по умолчанию.

Версия LINQ:

int duplicated = references.SelectMany( p => p.Value )
                           .GroupBy(x => x)
                           .Where(g => g.Count() > 1)
                           .Count();
1 голос
/ 24 ноября 2010

Можете ли вы использовать ContainsValue для проверки дубликатов? Из того, что вы описали, видно, что у вас есть только дубликаты, если значения совпадают.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...