контейнер с составным ключом.
От: Sergey_BG Россия  
Дата: 19.03.24 22:01
Оценка:
Подскажите, пожалуйста, есть ли какой нибудь контейнер поддерживающий составной ключ с динамической длинной?

Задача:
Есть структура с полями. И для нее идеально подошёл boost::multy_index_container. Можно индексировать и сортировать данные по любому полю структуры.

Но пришлось поменять одно поле в структуре на vector идентификаторов. И хотелось бы быстро находить все структуры в которых ключ содержит требуемый идентификатор. Но ничего не приходит в голову кроме полного перебора. Длина вектора очень произвольная.

Заранее спасибо!
Сергей
Re: контейнер с составным ключом.
От: reversecode google
Дата: 19.03.24 22:08
Оценка:
ничего не понял
но посмотрите в примеры буст мультикея
там рассматриваются разные вариации того как можно построить мультикей
и сабсет итд
Re: контейнер с составным ключом.
От: vopl Россия  
Дата: 20.03.24 11:17
Оценка: 2 (1)
Здравствуйте, Sergey_BG, Вы писали:

S_B>Подскажите, пожалуйста, есть ли какой нибудь контейнер поддерживающий составной ключ с динамической длинной?


S_B>Задача:

S_B>Есть структура с полями. И для нее идеально подошёл boost::multy_index_container. Можно индексировать и сортировать данные по любому полю структуры.

S_B>Но пришлось поменять одно поле в структуре на vector идентификаторов. И хотелось бы быстро находить все структуры в которых ключ содержит требуемый идентификатор. Но ничего не приходит в голову кроме полного перебора. Длина вектора очень произвольная.


S_B>Заранее спасибо!


Boost Multi-index может только ассоциации типа one-one (уникальные индексы) и оne-many (не уникальные), в твоем же случае имеет место many-many, поэтому Boost Multi-index пролетает. Придется мутить что то кастомное, структурно типа такого
struct MyElement
{
    std::vector<Identifier> identifiers;
};

struct MyIndex
{
    std::map<Identifier, std::set<MyElement*>> id2els;
    
    void add(MyElement* e)
    {
        for(Identifier id : e->identifiers)
            id2els[id].insert(e);
    }

    void del(MyElement* e)
    {
        for(Identifier id : e->identifiers)
        {
            auto iter = id2els.find(id);
            assert(id2elements.end() != iter);
            
            std::set<MyElement*>& els = iter->second;
            assert(els.contains(e));
            els.remove(e);
            if(els.empty())
                id2els.erase(iter);
        }
        
        //или, если не волнует мусорная пустота, можно вместо этого огорода сделать попроще
        //for(Identifier id : e->identifiers)
        //    id2elements[id].remove(e);
        
    }

    const std::set<MyElement*>& find(Identifier id) const
    {
        if(auto iter = id2els.find(id); id2els.end() != iter)
            return iter->secind;
            
        static const std::set<MyElement*> emptyResult;
        return emptyResult;
    }
};
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.