Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Знатокам STL - тривиальная задача с map

4
14 октября 2004 года
mike
3.7K / / 01.10.2002
Есть записи:

id количество
01 2
02 3
04 5
02 5
06 7
....
05 5

id не уникален. Записей много.

Нужно сгрупировать по id и отсортировать по IP, как это лучше сделать на C++ ?

Я использую STL map:

 
Код:
typedef std::map<long,long> TMap;
TMap map;


Добавление элемента:

 
Код:
void Add(crc,count) {
    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++) {
// Вывод тут
}
}

Можно ли сразу выводить сортируя ? Или придется сначала группировать, а потом сортировать ?
1
14 октября 2004 года
kot_
7.3K / / 20.01.2000
Цитата:
Originally posted by mike
Есть записи:

id количество
01 2
02 3
04 5
02 5
06 7
....
05 5

id не уникален. Записей много.

Нужно сгрупировать по id и отсортировать по IP, как это лучше сделать на C++ ?

Я использую STL map:

 
Код:
typedef std::map<long,long> TMap;
TMap map;


Добавление элемента:

 
Код:
void Add(crc,count) {
    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.

4
14 октября 2004 года
mike
3.7K / / 01.10.2002
Цитата:
Originally posted by kot_

Используй partial_sort или stable_sort. Обе функции объявлены в algorithm.



Я правильно понимаю, что нужно все загнать в вектор и потом уже сортировать?

368
14 октября 2004 года
rostyslav
629 / / 13.07.2004
Цитата:
Originally posted by mike


Я правильно понимаю, что нужно все загнать в вектор и потом уже сортировать?


А для чего вектор? Если есть qsort?

1
15 октября 2004 года
kot_
7.3K / / 20.01.2000
Цитата:
Originally posted by mike


Я правильно понимаю, что нужно все загнать в вектор и потом уже сортировать?


Кстати я тоже не понял - зачем вектор? Функция принимает указатель на первый и последний элемент последовательности - т.е. итератор.

4
15 октября 2004 года
mike
3.7K / / 01.10.2002
Цитата:
Originally posted by kot_

Кстати я тоже не понял - зачем вектор? Функция принимает указатель на первый и последний элемент последовательности - т.е. итератор.



То есть, структура может быть любая?

А почему stable_sort, почему не просто sort ??

368
15 октября 2004 года
rostyslav
629 / / 13.07.2004
Цитата:
Originally posted by mike


То есть, структура может быть любая?

А почему stable_sort, почему не просто sort ??


Если записываешь данные в map, то sort и table_sort лишнее.

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

4
15 октября 2004 года
mike
3.7K / / 01.10.2002
Цитата:
Originally posted by kot_

Кстати я тоже не понял - зачем вектор? Функция принимает указатель на первый и последний элемент последовательности - т.е. итератор.



Не понял ?

Так что-ли можно ??

TMap::iterator it;
stable_sort(it.begin(), it.end(),trecord_compare());

1
15 октября 2004 года
kot_
7.3K / / 20.01.2000
Цитата:
Originally posted by mike


Не понял ?

Так что-ли можно ??

TMap::iterator it;
stable_sort(it.begin(), it.end(),trecord_compare());


Слушай, я как то сразу затупил - а как ты собираешься записывать неуникальные иды в мап?
Хотел набросать тебе пример кода - и понял свою глупость.
В товоем случае мне кажется лучше использовать multimap. В справке есть достаточно неплохой пример.

4
15 октября 2004 года
mike
3.7K / / 01.10.2002
Цитата:
Originally posted by kot_

Слушай, я как то сразу затупил - а как ты собираешься записывать неуникальные иды в мап?
Хотел набросать тебе пример кода - и понял свою глупость.
В товоем случае мне кажется лучше использовать multimap. В справке есть достаточно неплохой пример.



Да у меня получилось следующее. Под Borland C++ Builder все работает, а в GNU C++ никак. (а мне именно там надо)

Выдает огромную плену ошибок

Код:
#include <stdlib.h>
#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 */
4
15 октября 2004 года
mike
3.7K / / 01.10.2002
Вот пелена
1
16 октября 2004 года
kot_
7.3K / / 20.01.2000
Может имеет смысл перегрузить оператор меньше чем, вместа класса trecord_compare? Попробуй.
4
16 октября 2004 года
mike
3.7K / / 01.10.2002
Цитата:
Originally posted by kot_
Может имеет смысл перегрузить оператор меньше чем, вместа класса trecord_compare? Попробуй.



Это как ?

1
18 октября 2004 года
kot_
7.3K / / 20.01.2000
Цитата:
Originally posted by mike


Это как ?


Т.е. вместо класса trecord_compare использовать перегрузку оператора:

 
Код:
bool operator < (const TRecord*& lhs, const TRecord*& rhs) {
        return lhs->count < rhs->count;
        }

Тогда функция может быть записана так
 
Код:
std::stable_sort(vector.begin(), vector.end());

возможно какие то нюансы реализации компилятора или библиотек?
4
18 октября 2004 года
mike
3.7K / / 01.10.2002
Цитата:
Originally posted by kot_
возможно какие то нюансы реализации компилятора или библиотек?



Все, решил :) Пришлось использовалось

typedef std::vector<TRecord> TVector;

вместо

typedef std::vector<TRecord*> TVector;

И все работает. Первый вариант не работал и с GNU C++ STL и с STLPortp

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог