C # - нужны предложения по улучшению раздела кода - PullRequest
0 голосов
/ 06 мая 2009

У меня есть функция, которая получает три разных объекта "люди" и генерирует новый объект "совместимость" на основе объединенных значений в объектах "люди".

Однако примерно в 1/3 времени три объекта "люди", которые он получает в качестве входных данных, являются такими же, как и прежде, хотя, возможно, в другом порядке. В этих случаях я НЕ хочу создавать новый объект «счет», а просто возвращаю значение, содержащееся в существующем объекте.

Первоначально программа просто просматривает список <> объектов «совместимости», ища тот, который принадлежит этим трем «людям» (поскольку каждый объект «совместимости» содержит массив объектов людей). Этот метод очень медленный, учитывая, что существует более тысячи объектов «совместимости» и более миллиона объектов «людей».

У меня была идея использовать словарь, где ключ - это число, которое я сгенерировал, скомбинировав значения идентификаторов объектов трех человек в один UInt64 с использованием XOR, и сохранив объекты партитуры в виде значений словаря, а не в списке. Это сокращает время примерно вдвое и является приемлемым с точки зрения производительности по времени, но слишком много коллизий и слишком часто возвращает неправильный результат.

Буду очень признателен за любые предложения или указатели.

Редактировать: Чтобы добавить к исходному вопросу, у каждого объекта "люди" есть куча других полей, которые я мог бы использовать, но проблема в том, чтобы сделать ключ УНИКАЛЬНЫМ и КОММУТАТИВНЫМ.

Ответы [ 6 ]

5 голосов
/ 06 мая 2009

Я думаю, что вы смотрите на вещи слишком сложным образом. Возьмите 3 значения PersonID и отсортируйте их так, чтобы они всегда были в одном и том же порядке, независимо от того, в каком порядке они были переданы. Затем установите значение в хеш-таблице, используя три PersonID в качестве ключа, разделенных дефисом или некоторыми другой символ, который не встречается в значении PersonID. Затем, позже, проверьте, есть ли значение в хеш-таблице с этим ключом.

Так что, если три PersonID - это 10, 5 и 22, хеш-ключ может быть что-то вроде "5-10-22".

1 голос
/ 06 мая 2009

Создание ключа путем объединения объектов после сортировки трио в заранее определенном порядке.

0 голосов
/ 06 мая 2009

при условии, что все объекты Person являются уникальными, сохраните UUID в объекте.

в вашей функции статически хранит квад (P1, P2, P3, V), где P1, P2, P3 - это UUID объекта Person, отсортированные (чтобы избежать проблем с упорядочением), а V - результат предыдущего вычисления.

тогда ваша функция проверяет, есть ли запись для этой тройки людей, если она не выполняет работу и сохраняет ее.

Вы можете сохранить значения (P1, P2, P3, V) в словаре, просто отключите некоторые хэш-значения из трех значений P

0 голосов
/ 06 мая 2009

Если вы хотите хранить все в памяти и не использовать базу данных, я бы порекомендовал что-то похожее на древовидную структуру. Предполагая, что ваши идентификаторы объектов сортируются, а порядок не имеет значения, вы можете сделать это с помощью вложенных словарей.

А именно, Dictionary<Key, Dictionary<Key, Dictionary<Key, Compatibility>>> должен добиться цели. Сортируйте идентификаторы и используйте самое низкое значение во внешнем словаре, следующее значение в следующем и окончательное значение, чтобы найти объект совместимости. Таким образом, столкновений не будет, и поиск должен быть достаточно быстрым.

Или, теперь, когда я снова думаю, это не должно быть настолько сложным. Просто используйте строку в качестве ключа и объедините идентификаторы вместе в отсортированном порядке с "!" или что-то еще, что не встречается в идентификаторах.

0 голосов
/ 06 мая 2009

Почему бы не использовать имена людей в качестве словарного ключа? (Сначала сортируйте имена, чтобы порядок передачи не имел значения.) IE, Джон, Алиса и Боб становятся чем-то вроде my_dictionary ["Alice_Bob_John"] <- если этот ключ существует, вы уже вычислили счет, в противном случае вам нужно его вычислить. В качестве альтернативы моему хакингу строк выше, вы можете использовать структуру: </p>

NameTriple n = new NameTriple("John", "Alice", "Bob");
// NameTriple internally sorts the names.
my_dictionary[n] ...
0 голосов
/ 06 мая 2009

Лучшим вариантом будет пользовательский класс IEqualityComparer. Объявите свой Dictionary как этот

Dictionary<List<People>, Compatability> people = 
    new Dictionary<List<People>, Compatability>(new PersonListComparer());

Вам нужно будет создать класс PersonListComparer, который реализует IEqualityComparer<List<People>>. Вам нужно реализовать два метода, один из которых получает хеш-код, а другой сравнивает равенство. Dictionary будет использовать GetHashCode, чтобы определить, ВОЗМОЖНО ли равны два списка, и метод Equals, чтобы определить, действительно ли они равны (другими словами, хеш-код быстр, но может давать ложное срабатывание, но никогда не ложное отрицательный). Используйте существующий алгоритм хеширования (XOR) для GetHashCode, а затем просто объедините два списка явно в методе Equals.

Это должно сработать!

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