Здравствуйте, ss_sa, Вы писали:
_>Есть std::map <string, vector> _>Нужно рассортировать этот map не по string а по значению vector.size() _>Как это сделать?
Мда я в шоке. В кои веки решил изучить сегодняшний С++ по Страуструпу, а то вообще отстал от жизни, ну и заодно и что-то полезное написать, а тут опять те же грабли — если копнуть глубже то стандартная библиотека малопригодна для более менее сложных приложений. И стоило отменять указатель void*, вводить namespaces и вообще уродовать С, все равно ведь ручками придется писать. И чем тогда С++ лучше С?
Есть std::map <string, vector>
Нужно рассортировать этот map не по string а по значению vector.size()
Как это сделать?
Re: map и сортировка по значению
От:
Аноним
Дата:
14.09.07 14:28
Оценка:
Здравствуйте, ss_sa, Вы писали:
_>Есть std::map <string, vector> _>Нужно рассортировать этот map не по string а по значению vector.size() _>Как это сделать?
Завести дополнительную структуру данных.
map — это ассоциативный контейнер и для таких целей не предназначен.
Здравствуйте, ss_sa, Вы писали:
_>Есть std::map <string, vector> _>Нужно рассортировать этот map не по string а по значению vector.size() _>Как это сделать?
Здравствуйте, ss_sa, Вы писали:
_>Есть std::map <string, vector> _>Нужно рассортировать этот map не по string а по значению vector.size()
если эта std::map не жёстко прописана в интерфейсе, то имеет смысл заменить её на boost::multi_index_container
Re[2]: map и сортировка по значению
От:
Аноним
Дата:
14.09.07 14:42
Оценка:
Здравствуйте, Bell, Вы писали:
B>Здравствуйте, ss_sa, Вы писали:
_>>Есть std::map <string, vector> _>>Нужно рассортировать этот map не по string а по значению vector.size() _>>Как это сделать?
B>Завести вротой B>
B>map<size_t, vector*>
B>
Тогда уж лучше банальный vector< vector* > и сортировать его по мере необходимости.
А иначе если ты какой из векторов изменишь, то будет твой map совсем неактуален.
Здравствуйте, ss_sa, Вы писали:
_>Есть std::map <string, vector> _>Нужно рассортировать этот map не по string а по значению vector.size() _>Как это сделать?
можно перефразировать задачу и написать так:
Здравствуйте, ss_sa, Вы писали:
_>Мда я в шоке. В кои веки решил изучить сегодняшний С++ по Страуструпу,
ну так изучи для начала что такое map, для чего он предназначен а для чего — нет
... << RSDN@Home 1.2.0 alpha rev. 743>>
Re[3]: map и сортировка по значению
От:
Аноним
Дата:
15.09.07 08:11
Оценка:
_>Мда я в шоке. В кои веки решил изучить сегодняшний С++ по Страуструпу, а то вообще отстал от жизни, ну и заодно и что-то полезное написать, а тут опять те же грабли — если копнуть глубже то стандартная библиотека малопригодна для более менее сложных приложений. И стоило отменять указатель void*, вводить namespaces и вообще уродовать С, все равно ведь ручками придется писать. И чем тогда С++ лучше С?
_>Мда я в шоке. В кои веки решил изучить сегодняшний С++ по Страуструпу, а то вообще отстал от жизни, ну и заодно и что-то полезное написать, а тут опять те же грабли — если копнуть глубже то стандартная библиотека малопригодна для более менее сложных приложений. И стоило отменять указатель void*, вводить namespaces и вообще уродовать С, все равно ведь ручками придется писать. И чем тогда С++ лучше С?
Ты написал полную ерунду. Чем больше ты будешь узнавать о современном С++, тем более ты будешь это осознавать.
Здравствуйте, Odi$$ey, Вы писали:
_>>Мда я в шоке. В кои веки решил изучить сегодняшний С++ по Страуструпу,
OE>ну так изучи для начала что такое map, для чего он предназначен а для чего — нет
Там написано что это контейнер, типа vector и других. Нет а правда нельзя подшаманить раз C++ такой гибкий язык как все говорят, ну там сделать свой класс-потомок или еще как?
Здравствуйте, ss_sa, Вы писали:
_>Здравствуйте, Odi$$ey, Вы писали:
_>>>Мда я в шоке. В кои веки решил изучить сегодняшний С++ по Страуструпу,
OE>>ну так изучи для начала что такое map, для чего он предназначен а для чего — нет
_>Там написано что это контейнер, типа vector и других. Нет а правда нельзя подшаманить раз C++ такой гибкий язык как все говорят, ну там сделать свой класс-потомок или еще как?
Для начала надо определиться с постановкой задачи. Можно на словах услышать что ты хочешь сделать?
_>Мда я в шоке.
Я тоже. С утра на трезвую голову Не смог вечером удержать полет фантазии _>skipped
Выше предлагалось использовать map для хранения указателей, но лучше использовать multimap, так как могут встретиться одинаковые длины. Вот что-то более-менее похожее на правду.
Здравствуйте, ss_sa, Вы писали:
_>Здравствуйте, Odi$$ey, Вы писали:
_>>>Мда я в шоке. В кои веки решил изучить сегодняшний С++ по Страуструпу,
OE>>ну так изучи для начала что такое map, для чего он предназначен а для чего — нет
_>Там написано что это контейнер, типа vector и других. Нет а правда нельзя подшаманить раз C++ такой гибкий язык как все говорят, ну там сделать свой класс-потомок или еще как?
Типа vector, но не такой. Есть три вида контейнеров: с произвольным доступом, с последовательным и ассоциативные. map — ассоциативный. Сделан чаще на двоичном дереве (ч/б). Следовательно его нельзя сортировать, так как он и так упорядочен, согласно какому-то ключу. Т.е. одно дерево — один ключ. В даннай задаче нужно сортировать по двум ключам, значит map не подходит. Как обходное решение, можно использовать несколько контейнеров. Основной и дополнительные, с указателями (а лучше итераторами) на элементы в основном, и разными порядками сортировки. Помнить о валидности указателей/итераторов.
Здравствуйте, Анатолий Широков, Вы писали:
OE>>>ну так изучи для начала что такое map, для чего он предназначен а для чего — нет
_>>Там написано что это контейнер, типа vector и других. Нет а правда нельзя подшаманить раз C++ такой гибкий язык как все говорят, ну там сделать свой класс-потомок или еще как?
АШ>Для начала надо определиться с постановкой задачи. Можно на словах услышать что ты хочешь сделать?
Да вообщем-то так учебная задача, есть web лог, нужно
1. подсчитать все страницы
2. вывести на каждую страницу статистику те сколько раз посещали, ip, браузера, и ид
Охото сделать все на С++, по последним достижениям техники а то чувствую отстал от жизни.
В принцепе все получилось, но вот отсортировать полученый массив по количеству посещений почему-то не удалось
Здравствуйте, sc, Вы писали:
_>>Там написано что это контейнер, типа vector и других. Нет а правда нельзя подшаманить раз C++ такой гибкий язык как все говорят, ну там сделать свой класс-потомок или еще как?
sc>Типа vector, но не такой. Есть три вида контейнеров: с произвольным доступом, с последовательным и ассоциативные. map — ассоциативный.
Вообщем они все имеют доступ еще и по итератору.
sc>В даннай задаче нужно сортировать по двум ключам, значит map не подходит. Как обходное решение, можно использовать несколько контейнеров. Основной и дополнительные, с указателями (а лучше итераторами) на элементы в основном, и разными порядками сортировки. Помнить о валидности указателей/итераторов.
Спасибо я понял что без другого map не обойтись.
зы Нет ну надо же оказывается С++ опять надо учить раньше сидел на старом диалекте BCC и спокойно клепал програмки, а оказывается жизнь ушла вперед и С++ это теперь совсем другой язык который был 8 лет назад.
Здравствуйте, sc, Вы писали:
sc>Выше предлагалось использовать map для хранения указателей, но лучше использовать multimap, так как могут встретиться одинаковые длины. Вот что-то более-менее похожее на правду.
да multimap лучше.
sc>
<skipped> _>А что правда templates наследование не поддерживают?
Почему же? Поддерживают.
template <
class Key,
class Type,
class Compare = std::less<Key>,
class Allocator = std::allocator<std::pair<const Key, Type> > >
class mmap: public std::map<Key, Type, Compare, Allocator>
{
};
Можно добавить вектор/map multimap'ов (как член mmap'а) и методы добавления/удаления/выбора сортировщиков. Определить методы добавления/удаления в/из mmap. Определить копиктор и =. В общем следить за валидностью указателей/итераторов.
Здравствуйте, ss_sa, Вы писали:
_>Здравствуйте, Анатолий Широков, Вы писали:
OE>>>>ну так изучи для начала что такое map, для чего он предназначен а для чего — нет
_>>>Там написано что это контейнер, типа vector и других. Нет а правда нельзя подшаманить раз C++ такой гибкий язык как все говорят, ну там сделать свой класс-потомок или еще как?
АШ>>Для начала надо определиться с постановкой задачи. Можно на словах услышать что ты хочешь сделать?
_>Да вообщем-то так учебная задача, есть web лог, нужно _>1. подсчитать все страницы _>2. вывести на каждую страницу статистику те сколько раз посещали, ip, браузера, и ид _>Охото сделать все на С++, по последним достижениям техники а то чувствую отстал от жизни.
Вот это совсем другое дело. Вот набросок, который можно расширить по желанию:
#include <iostream>
#include <string>
#include <sstream>
#include <map>
#include <algorithm>
// запись в логеstruct entry
{
std::string datetime;
std::string page;
std::string ip;
std::string browser;
friend std::istream& operator>>(std::istream &stream, entry &e)
{
entry t;
if( !(stream >> t.datetime) )
return stream;
if( !(stream >> t.page) )
return stream;
if( !(stream >> t.ip) )
return stream;
if( !(stream >> t.browser) )
return stream;
e = t;
return stream;
}
}; // struct entry..
// менеджер сбора статистикиclass statistic
{
private: // данные
// статистика посещения страниц
std::map<std::string, int> page_to_visit;
// информация о количестве визитов
std::multimap<int, std::string> visit_to_page;
public:
// запросить статистику по количеству визитов посещенных страницconst std::multimap<int, std::string>& get_page_by_visit() const
{
return visit_to_page;
}
// обработать запись лога
statistic& process(const entry &e)
{
// прочитали количество визитов данной страницы
// до регистрации новой записи логеint visit_count = page_to_visit[e.page]++;
if( visit_count ) {
// запросили диапазон соответствующий полученному
// количеству визитов
std::pair<
std::multimap<int, std::string>::iterator,
std::multimap<int, std::string>::iterator>
range = visit_to_page.equal_range(visit_count);
// ищем в нем нашу страницуfor(std::multimap<int, std::string>::iterator i = range.first; i != range.second; i++)
// если страница найденаif( i->second == e.page )
{
// удаляем старое упоминание поскольку число вхождений увеличилось
// и регистрируем запись с новым количеством
visit_to_page.insert(
visit_to_page.erase(i),
std::make_pair<int, std::string>(visit_count+1, e.page)
);
break;
}
} else {
// регистрируем первый раз
visit_to_page.insert(
std::make_pair<int, std::string>(visit_count+1, e.page)
);
}
return *this;
} // add..
}; // class statistic..
// вспомогательный функтор, который выполняет роль посредника
// между алгоритмом for_each и менеждером статистикиstruct process_entry
{
private:
statistic *mng;
public:
process_entry(statistic &mng) : mng(&mng) {}
void operator()(const entry &e)
{
mng->process(e);
}
}; // struct process_entry..
// вспомогательный класс для вывода пары в потокstruct visit_count_page
{
const std::pair<const int, std::string> *p;
visit_count_page(const std::pair<const int, std::string> &r) : p(&r) {}
friend std::ostream& operator<<(std::ostream &stream, const visit_count_page &p)
{
stream << p.p->first << " " << p.p->second;
return stream;
}
}; // struct visit_count_page..int main()
{
statistic mng;
std::istringstream stream(
"200709152019 index.html 127.0.0.1 IE7\n"
"200709152025 index.html 127.0.0.1 IE7\n"
"200709152125 index.html 127.0.0.1 IE7\n"
"200709152225 overview.html 127.0.0.1 IE7\n"
"200709152325 overview.html 127.0.0.1 IE7\n"
"200709152327 about.html 127.0.0.1 IE7\n"
);
std::for_each(
std::istream_iterator<entry>(stream),
std::istream_iterator<entry>(),
process_entry(mng)
);
const std::multimap<int, std::string> m = mng.get_page_by_visit();
// вывод статистики по количеству посещений в порядке убывания интереса
std::copy(
m.rbegin(),
m.rend(),
std::ostream_iterator<visit_count_page>(std::cout, "\n")
);
return 0;
}
Здравствуйте, Анатолий Широков, Вы писали:
АШ>>>Для начала надо определиться с постановкой задачи. Можно на словах услышать что ты хочешь сделать?
_>>Да вообщем-то так учебная задача, есть web лог, нужно _>>1. подсчитать все страницы _>>2. вывести на каждую страницу статистику те сколько раз посещали, ip, браузера, и ид _>>Охото сделать все на С++, по последним достижениям техники а то чувствую отстал от жизни.
АШ>Вот это совсем другое дело. Вот набросок, который можно расширить по желанию:
АШ>
АШ>...
АШ>
Спасибо, я вообщем и сам написал, но ваш пример конечно интереснее.
Здравствуйте, sc, Вы писали:
sc>Здравствуйте, ss_sa, Вы писали:
sc><skipped> _>>А что правда templates наследование не поддерживают? sc>Почему же? Поддерживают. sc>
template <
sc> class Key,
sc> class Type,
sc> class Compare = std::less<Key>,
sc> class Allocator = std::allocator<std::pair<const Key, Type> > >
sc>class mmap: public std::map<Key, Type, Compare, Allocator>
sc>{
sc>};
sc>Можно добавить вектор/map multimap'ов (как член mmap'а) и методы добавления/удаления/выбора сортировщиков. Определить методы добавления/удаления в/из mmap. Определить копиктор и =. В общем следить за валидностью указателей/итераторов.
Ага те можно перезагрузить метод сортировки, добавить свой как в класическом С++...
Собственно если нужно сменить тип сортировки, можно использовать rebuild_set — операция дорогая но вполне валидная. Тот же финт можно провернуть с любым из контейнеров multiset, map, multimap, только не забывайте что MyComparer::operator< это больше чем просто предикат для сортировки. Предикат также определяет равенство элементов через !predicat(a, b) && !predicat(b, a), (например при поиске, find по ключу). Особенно это актуально для контейнеров типа set и map: контейнеры следят за уникальностью своего контента и при пересортировке некоторые элементы могут быть не вставлены.
"ss_sa" <38616@users.rsdn.ru> wrote in message news:2657830@news.rsdn.ru... > Есть std::map <string, vector> > Нужно рассортировать этот map не по string а по значению vector.size() > Как это сделать?
Странно, что никто не упомянул boost::multi_index...
Posted via RSDN NNTP Server 2.1 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, ss_sa, Вы писали:
sc>>В даннай задаче нужно сортировать по двум ключам, значит map не подходит. Как обходное решение, можно использовать несколько контейнеров. Основной и дополнительные, с указателями (а лучше итераторами) на элементы в основном, и разными порядками сортировки. Помнить о валидности указателей/итераторов.
_>Спасибо я понял что без другого map не обойтись.
Можно обойтись. boost::multi_index.
Вообще, у контейнеров жёстко соединены две роли: хранилище данных и доступ к ним (последовательный, по ключу, по индексу и т.д.)
На самом деле, это необязательно. Например, таблица у базы данных состоит из собственно файла с таблицей (пусть даже упорядоченного по главному ключу) и набора индексных файлов.
Или компромисс с перекрёстными map'ами.
Подход с двумя перекрёстными map'ами подкупает своей простотой, но таит ряд подводных камней
— Требуется поддерживать их в согласованном состоянии. Добавляя в один map, нужно добавлять и в другой.
— Накладные расходы. Ключ хранится в двух контейнерах сразу.
— Итерирование по первому и второму ключам различается: элементами будут не pair<K,V> и pair<V,K>, а, например, pair<K,V> и pair<V*,K*> либо pair<K,V*> и pair<V,K*> (где K и V — первичный ключ и значение, выступающее вторичным ключом)
Придётся или зарезать интерфейс — свести его к простейшим действиям (добавить, удалить, найти по K, найти по V), или основательно заняться рукоделием, обеспечивая целостность и удобство такого объединённого контейнера.
boost::multi_index хранит элементы целостно: один узел — один элемент. Итераторы по всем способам упорядочения ссылаются на одни и те же элементы. Меняется только порядок обхода (в каждом узле есть батарея указателей, создающая нужные списки и деревья).