Pull to refresh

Comments 8

А если у человека есть имя и адрес - оба поля строковые? Искать вы все еще можете только по одному конкретному полю-ключу, которое используется для сравнения элементов.

Т.е. у вас есть объект у него есть одно особое поле - ключ. Т.е. вам тут лучше уже подходит std::map, а не std::set. В качестве ключа используйте ваш ключ, в качестве данных - все остальные данные. Это поле вообще можно отдельно от данных держать.

Только если у вас объекты, которые вы в разных местах сортируете и ищите по разным полям, то тут неприятность - тут плохо будет заводить новый тип для каждого случая, и у вас будет дублирование поля ключей (одна копия в ключах map, другая - в поле объекта).

В этом частном случае действительно лучше подойдет std::set, но можно гораздо проще, чем у вас. Достаточно сделать конструктор или статический фабричный метод, который создаст вам объект с нужным ключем, а все остальные поля оставит пустыми. Действительно тяжелые объекты редко сами настолько большие, что нельзя одну копию завести на стеке во время поиска. Они большие, потому что что-то в куче заводят, ну так достаточно только допустить существование объекта лишь с ключевым полем для сравнений и не выделять там все остальное:

std::set<Person> persons;
if (persons.find(Person::WithName("Vasya")) != persons.end())

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

/.Т.е. у вас есть объект у него есть одно особое поле - ключ. Т.е. вам тут лучше уже подходит std::map, а не std::set. В качестве ключа используйте ваш ключ, в качестве данных - все остальные данные. Это поле вообще можно отдельно от данных держать.

Инода нужен доступ из методов объекта «все остальные данные» к ключу, а этот объект в std::map не знает, под каким ключом он лежит. Или надо передать этот объект в к-л функцию, и опять же, если функции интересен также и ключ, передавать его отдельно? Это весьма неудобно. Собственно, для этих случаев std::set и предназначен, для остальных, я согласен, std::map — самый естественный выбор.

Ну если ключ какой-то особый, потому что по нему вы ищите, то можно его и отдельно передавать. А если уж так хочется, то используйте set как я указал с фабричным методом.

Достаточно сделать конструктор или статический фабричный метод, который создаст вам объект с нужным ключом, а все остальные поля оставит пустыми. Действительно тяжелые объекты редко сами настолько большие, что нельзя одну копию завести на стеке во время поиска. Они большие, потому что...

Да, это один из возможных вариантов использования std::set, я о нем не упоминал, хотя он вполне работающий. Собственно, решения, предлагаемые в этой статье родились из некоей эстетической неудовлетворенности таким подходом, хотя он, безусловно, рабочий, я согласен.

По опыту скриптовых языков хэш-таблицы используются с одним ключом, можно ключ сделать составным "фамилия______имя". Для сложных поисков используется внешняя база данных.

Сейчас изучаю С и в нем тяжело без хэшей.

В си вообще тяжело. Деревьев там тоже нет, как и списков с динамическими массивами (сами всё писать будете). Поэтому мне лично очень тяжело читать кодовые базы на голых сях - куча велосипедов (часто на макросах) с отсутствием какой-либо типобезопасности, т.е. фигачат на void* всё. Туда же сишные вариадики, минимум по две функции для выделения и освобождения на каждую структуру в коде... В общем, плюсовику больно.

А вот функции, возвращающих «настоящую» нижнюю грань, то есть ближайший объект, меньший запрашиваемого ключа

Такой функции нет, так как непонятно, что возвращать, если запрашиваемый объект - самый первый. before_begin есть только у std::forward_list.

Вероятно, вы правы. Хотя, я вернул бы end(). Но то, что end() будет больше, чем итератор, который указывал бы на запрашиваемый ключ если бы оный ключ был в коллекции... этот факт, пожалуй, да, нарушает стройность всей картины.

Sign up to leave a comment.

Articles