#c #search #struct #find #containers
#c #Поиск #структура #Найти #контейнеры
Вопрос:
У меня есть структура, которую мне нужно поместить в контейнер на C . вот структура:
struct PDCUTestMessage
{
string name;
unsigned char id;
int numberOfParameters;
string param1Name;
string param2Name;
string param3Name;
string param4Name;
string param5Name;
boost::function<void(vector<unsigned char>)> process;
PDCUTestMessage();
PDCUTestMessage(string_name, unsigned char _id, int _numberOfParameters, boost::function<void(vector<unsigned char>)> _process): name(_name), id(_id), numberOfParameters(_numberOfParameters), process(_process){}
};
Мне понадобится около 65 таких структур, поэтому я хочу поместить их в контейнер (я думаю, список, вектор или карту). Мне нужно иметь возможность обращаться к указателю функции (процессу) данного PDCUTestMessage с помощью двух разных значений поиска: name и id. Я заметил, что map допускает только одно значение и один ключ. Есть ли какой-либо контейнер, который позволил бы мне быстро искать PDCUTestMessage, использующий имя или идентификатор в качестве ключа? И как бы я написал поиск и получил доступ к функции, на которую указывает указатель?
Я надеюсь, что это имеет смысл. Дайте мне знать, если вам нужны дополнительные разъяснения.
Спасибо!
Комментарии:
1. Если у вас есть «около 65» объектов, использование std::vector было бы неплохо.
Ответ №1:
Поскольку вы уже используете boost, здесь может пригодиться библиотека контейнеров boost.multi-index. В частности, рассмотрите примеры в разделе руководства по множественной сортировке.
Комментарии:
1. Это выглядит многообещающе. Я вроде как новичок в C , поэтому надеюсь, что смогу это понять. Есть ли другие ссылки или примеры использования мультииндексации в этом контексте?
Ответ №2:
Поскольку в вашем контейнере всего 65 элементов, простой линейный поиск может быть достаточно быстрым для ваших нужд. Используйте имя в качестве ключа для вашей карты (или набора) и используйте std::find, когда вам нужно выполнить поиск по идентификатору.
Комментарии:
1. Я мало что сделал с maps и std::find. У меня сложилось впечатление, что вы можете выполнять поиск только с помощью find, используя ключ записи map, или, по крайней мере, это примеры, которые я нахожу. Есть ли у вас какие-либо примеры того, как я мог бы сделать это с помощью map и find? Кстати, ID будет наиболее часто используемым ключом. Итак, я бы настроил это в противоположность тому, что вы сказали? С идентификатором в качестве ключа и std::find с именем?
Ответ №3:
Как уже упоминалось Boost.Мультииндекс — это один из способов решения подобной проблемы. Это очень мощный и быстрый инструмент, но в большинстве случаев это просто означает медленную компиляцию и сложный код, не получая при этом особых других преимуществ.
65 элементов — это не так уж много, и, как упоминал Марк Рэнсом, линейный поиск может работать достаточно хорошо для того, что вы делаете. Это вам нужно измерить.
Другой способ сделать что-то — иметь std:: vector, содержащий сообщения (65 сообщений), и тогда у вас могут быть два отдельных контейнера, которые вы используете для поиска: первый — id-to-index, а второй — name-to-index. Индекс — это позиция сообщения в векторе. Что-то вроде этого:
class YourContainerClass
{
public:
bool lookupById(unsigned char id, PDCUTestMessageamp; message)
{
std::map<unsigned char, int>::iterator it = idToIndexMap.find(id);
if (it == idToIndexMap.end())
return false;
message = messages[*it];
return true;
}
bool lookupByName(const std::stringamp; name, PDCUTestMessageamp; message)
{
std::map<std::string, int>::iterator it = nameToIndexMap.find(id);
if (it == nameToIndexMap.end())
return false;
message = messages[*it];
return true;
}
private:
std::vector<PDCUTestMessage> messages;
std::map<unsigned char, int> idToIndexMap;
std::map<std::string, int> nameToIndexMap;
};
Для управления внутренними контейнерами ваша вставка должна выполнять работу с push_back в векторе сообщений и в то же время вставлять в две карты соответствующие объекты, чтобы найти индекс в векторе по идентификатору и имени.
Это всего лишь один из способов, как будет выглядеть API. Вы также могли бы обернуть сообщения в boost::shared_ptr, чтобы получить немного другой API. Это немного выходит за рамки вашего вопроса, потому что я также не знаю, как вы собираетесь использовать сообщения и время их жизни.
Я бы сказал, даже если Boost.MultiIndex — очень классный контейнер, он не должен быть первым вариантом. Есть много способов сделать это, и это сводится к конкретным проблемам, что имеет наибольший смысл.
Надеюсь, вы найдете то, что имеет наибольший смысл для вас.