Russian Qt Forum
Ноябрь 25, 2024, 06:08 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Замапить 2 контейнера  (Прочитано 7568 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Июнь 04, 2017, 08:45 »

Добрый день

Есть 2 контейнера (возможно с разным числом эл-тов). Для каждого эл-та в первом нужно найти какой ему соответствует во втором по ключам (ID + Name) или наоборот (Name + ID), порядок ключей задается юзером. Ключи не уникальны. Порядок поиска

- находим с таким же ID и Name
- иначе находим хотя бы с таким же ID
- иначе просто берем первый неиспользуемый из 2-го контейнера

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

Как это сделать "техничнее", по возможности избегая длинного и нудного кода? И еще: квадратичный перебор не запрещается (вряд ли эл-тов будет мульены), но все-таки хотелось бы без него (мы же приличные люди  Улыбающийся)

Спасибо
« Последнее редактирование: Июнь 04, 2017, 08:47 от Igors » Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #1 : Июнь 04, 2017, 18:49 »

Не очень понятно, почему вы упомянули, что порядок ID и Name может быть разный? Разве это не независимые поля структурки?
Первый неиспользуемый == один из тех, что остались незаюзанными после маппинга?
Что делать, если неиспользуемых нет?
Записан
Johnik
Крякер
****
Offline Offline

Сообщений: 339


Просмотр профиля
« Ответ #2 : Июнь 04, 2017, 19:24 »

можно глянуть boost multi_index_container
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #3 : Июнь 05, 2017, 00:24 »

Проще всего создать дополнительные индексы (мапы) для 2 контейнера.
Например что то типа

typedef QPair<QString,QString> id_name_index;
QMap<id_name_index, item_index> index_map;

В index_map сложим все индексы элементов второго контейнера, определяемые парой индексов. Далее "все элементарно".

Один вопрос только: что значит "берем первый неиспользуемый из 2-го контейнера"?
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Июнь 05, 2017, 11:08 »

Не очень понятно, почему вы упомянули, что порядок ID и Name может быть разный? Разве это не независимые поля структурки?
Поля независимые, порядок (приоритет) нахождения разный - противоречий нет
Первый неиспользуемый == один из тех, что остались незаюзанными после маппинга?
Да
Что делать, если неиспользуемых нет?
Ничего. Да, в первом может быть 10, во втором только 5 (или наоборот). Ну значит 5 и остались незамаплнены, невозможного не требуется

можно глянуть boost multi_index_container
Когда-то читал, не очень понимаю как он здесь может пригодиться

Проще всего создать дополнительные индексы (мапы) для 2 контейнера.
Например что то типа

typedef QPair<QString,QString> id_name_index;
QMap<id_name_index, item_index> index_map;

В index_map сложим все индексы элементов второго контейнера, определяемые парой индексов.
Я тоже попытался мудрить в этом духе, но потом вставил флажок прямо к ключ и if в оператор <  Улыбающийся   

Далее "все элементарно".
Скорее "тривиально"  Улыбающийся Но увы - длинновато. Получается 3 прохода, на каждом эл-т ищется в std::set и удаляется если найден. Может есть что покруче?

Один вопрос только: что значит "берем первый неиспользуемый из 2-го контейнера"?
Не понял - ну то и значит, первый (по порядку) которые еще не был замаплен на эл-т первого контейнерв
Записан
deMax
Хакер
*****
Offline Offline

Сообщений: 600



Просмотр профиля
« Ответ #5 : Июнь 05, 2017, 11:52 »

Скорее "тривиально"  Улыбающийся Но увы - длинновато. Получается 3 прохода, на каждом эл-т ищется в std::set и удаляется если найден. Может есть что покруче?
В set у вас храниться только id/имя? я бы второй массив, в два map с ключом по индексу и по имени засунул; а значение указатель на элемент во втором массиве и флаг использования. перебор ~ 3*n*log(n)
для каждого элемента в первом массиве находим через map соответствия, и так 3 прохода.

Можно для красоты в свой map обернуть, типа такого DuoMap<T1 key1, T2 key2, T value> и методы find(key1,key2), find(key1).

p.s. Еще можно таблицы в БД хранить, там своя оптимизация, вряд ли будет быстрее но кода будет меньше.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Июнь 05, 2017, 12:37 »

Ключ такой получился
Код
C++ (Qt)
struct CMuteKey {
CMuteKey( SInt32 numVer = 0, const QString & name = QString(),
 SInt32 entryIndex = -1, bool nameFirst = false ) :
mNumVer(numVer),
mName(name),
mEntryIndex(entryIndex),
mNameFirst(nameFirst)
{
}
 
bool operator < ( const CMuteKey & other ) const
{
if (mNameFirst) {
SInt32 match = mName.compare(other.mName);
if (match < 0) return true;
if (match > 0) return false;
 
if (mNumVer < other.mNumVer) return true;
if (mNumVer > other.mNumVer) return false;
}
else {
if (mNumVer < other.mNumVer) return true;
if (mNumVer > other.mNumVer) return false;
 
SInt32 match = mName.compare(other.mName);
if (match < 0) return true;
if (match > 0) return false;
}
 
return mEntryIndex < other.mEntryIndex;
}
 
// data members
SInt32 mNumVer;       // ID
QString mName;              //  Name
SInt32 mEntryIndex;  //  index in second container
bool   mNameFirst;            // sort order (true = name first)
};
 
Для первого контейнера - вектор таких ключей с mEntryIndex = -1 (не найдено). Для второго - std::set таких ключей с  mEntryIndex = i (индекс во втором). Ну и 3 прохода.
« Последнее редактирование: Июнь 05, 2017, 12:39 от Igors » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.1 секунд. Запросов: 22.