Знатокам STL - тривиальная задача с map
id количество
01 2
02 3
04 5
02 5
06 7
....
05 5
id не уникален. Записей много.
Нужно сгрупировать по id и отсортировать по IP, как это лучше сделать на C++ ?
Я использую STL map:
TMap map;
Добавление элемента:
TMap::iterator it = map.find(pid);
if (it!=map.end())
map.insert(make_pair(crc,count));
else map[crc]+=count;
}
Вывод списка элементов:
void Show() {
int i=1;
for(TMap::iterator it=map.begin();it!=map.end();it++) {
// Вывод тут
}
}
Можно ли сразу выводить сортируя ? Или придется сначала группировать, а потом сортировать ?
Есть записи:
id количество
01 2
02 3
04 5
02 5
06 7
....
05 5
id не уникален. Записей много.
Нужно сгрупировать по id и отсортировать по IP, как это лучше сделать на C++ ?
Я использую STL map:
TMap map;
Добавление элемента:
TMap::iterator it = map.find(pid);
if (it!=map.end())
map.insert(make_pair(crc,count));
else map[crc]+=count;
}
Вывод списка элементов:
void Show() {
int i=1;
for(TMap::iterator it=map.begin();it!=map.end();it++) {
// Вывод тут
}
}
Можно ли сразу выводить сортируя ? Или придется сначала группировать, а потом сортировать ?
Используй partial_sort или stable_sort. Обе функции объявлены в algorithm.
Используй partial_sort или stable_sort. Обе функции объявлены в algorithm.
Я правильно понимаю, что нужно все загнать в вектор и потом уже сортировать?
Я правильно понимаю, что нужно все загнать в вектор и потом уже сортировать?
А для чего вектор? Если есть qsort?
Я правильно понимаю, что нужно все загнать в вектор и потом уже сортировать?
Кстати я тоже не понял - зачем вектор? Функция принимает указатель на первый и последний элемент последовательности - т.е. итератор.
Кстати я тоже не понял - зачем вектор? Функция принимает указатель на первый и последний элемент последовательности - т.е. итератор.
То есть, структура может быть любая?
А почему stable_sort, почему не просто sort ??
То есть, структура может быть любая?
А почему stable_sort, почему не просто sort ??
Если записываешь данные в map, то sort и table_sort лишнее.
Но если эти данные уже в памяти, то загонять их еще и в map, не самый эффективный вариант.
Кстати я тоже не понял - зачем вектор? Функция принимает указатель на первый и последний элемент последовательности - т.е. итератор.
Не понял ?
Так что-ли можно ??
TMap::iterator it;
stable_sort(it.begin(), it.end(),trecord_compare());
Не понял ?
Так что-ли можно ??
TMap::iterator it;
stable_sort(it.begin(), it.end(),trecord_compare());
Слушай, я как то сразу затупил - а как ты собираешься записывать неуникальные иды в мап?
Хотел набросать тебе пример кода - и понял свою глупость.
В товоем случае мне кажется лучше использовать multimap. В справке есть достаточно неплохой пример.
Слушай, я как то сразу затупил - а как ты собираешься записывать неуникальные иды в мап?
Хотел набросать тебе пример кода - и понял свою глупость.
В товоем случае мне кажется лучше использовать multimap. В справке есть достаточно неплохой пример.
Да у меня получилось следующее. Под Borland C++ Builder все работает, а в GNU C++ никак. (а мне именно там надо)
Выдает огромную плену ошибок
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <map>
#include <algorithm>
#include <utility>
#include <vector>
#include "counter.h"
#include "mstring.h"
#include "shared.h"
#include "s_shared.h"
namespace report_cities {
typedef struct {
char *city;
unsigned long country;
unsigned long count;
} TRecord;
typedef std::map<unsigned long,TRecord*> TMap;
typedef std::vector<TRecord*> TVector;
class trecord_compare {
public:
bool operator()(const TRecord*& lhs, const TRecord*& rhs) {
return lhs->count > rhs->count;
}
};
int REPORT(
mString filename,
unsigned long sdate,
unsigned long edate,
int page) {
TLog l;
unsigned long res_count=0;
FILE *f=fopen(filename,"rb");
if (!f) return(0);
unsigned long end_pos=+SeekDate(f,edate);
fseek(f,SeekDate(f,sdate),SEEK_SET);
int count=0;
TMap map;
TVector vector;
while (ftell(f)<end_pos) {
count++;
fread(&l,1,sizeof(l),f);
if (l.time>=sdate && l.time<=edate) {
TMap::iterator it = map.find(l.city_crc);
if (it==map.end()) {
TRecord *rec=new TRecord;
rec->city=strdup(l.city);
rec->country=l.country;
rec->count=1;
map.insert(std::make_pair(l.city_crc,rec));
res_count++;
}
else {
(*it).second->count++;
}
}
}
fclose(f);
unsigned long total=0;
TMap::iterator it;
for (it = map.begin(); it != map.end(); ++it) {
vector.push_back(it->second);
total+=it->second->count;
}
std::stable_sort(vector.begin(), vector.end(),trecord_compare());
printf("%d\n",total);
TVector::iterator itv;
int i=0;
for (itv = vector.begin(); itv != vector.end(); ++itv) {
// Вывод результатов
i++;
free((*itv)->city);
delete (*itv);
}
return(res_count);
}
} /* of namespace */
Может имеет смысл перегрузить оператор меньше чем, вместа класса trecord_compare? Попробуй.
Это как ?
Это как ?
Т.е. вместо класса trecord_compare использовать перегрузку оператора:
return lhs->count < rhs->count;
}
Тогда функция может быть записана так
возможно какие то нюансы реализации компилятора или библиотек?
возможно какие то нюансы реализации компилятора или библиотек?
Все, решил :) Пришлось использовалось
typedef std::vector<TRecord> TVector;
вместо
typedef std::vector<TRecord*> TVector;
И все работает. Первый вариант не работал и с GNU C++ STL и с STLPortp