2009-05-06 6 views
0

У меня есть функция, которая получает три разных объекта «люди» и генерирует новый объект «совместимости», основанный на комбинированных значениях объектов «люди».C# - Нужны предложения по улучшению раздела кода

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

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

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

Любые предложения или указатели будут высоко оценены.

Редактировать: Чтобы добавить к исходному вопросу, каждый объект «people» имеет кучу других полей, которые я мог бы использовать, но проблема заключается в создании ключа, который является UNIQUE и COMMUTATIVE.

ответ

5

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

Таким образом, если три идентификатора PersonID являются 10, 5 и 22, хеш-ключ может быть чем-то вроде «5-10-22».

+0

Похоже, что я сделал бы это всего лишь одно примечание, если идентификаторы Person фиксированы, разделитель не требуется. Я бы нашел это немного более аккуратным. – PeteT

0

Ваш лучший вариант был бы обычным классом IEqualityComparer. Объявите ваш Dictionary как этот

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

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

Это должно сделать трюк!

0

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

NameTriple n = new NameTriple("John", "Alice", "Bob"); 
// NameTriple internally sorts the names. 
my_dictionary[n] ... 
+0

Если у вас есть люди объекты зачем использовать строки? Почему бы не использовать ссылку на объект. – Spence

1

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

0

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

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

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

0

Предполагая, что все объекты «Человек» уникальны, сохраните UUID в объекте.

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

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

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

Смежные вопросы