Структура для хранения значения по ранжированному ключу - PullRequest
4 голосов
/ 21 апреля 2009

Мне нужна структура для хранения значения, основанного на ключе с диапазоном. Моя реализация - C ++, поэтому любой STL или Boost был бы превосходным.

У меня в качестве ключа диапазона, которые двойные, и значение

  • [0,2) -> значение1
  • [2,5) -> значение2
  • [5,10) -> значение3
  • и т.д.

Так, чтобы при поиске 1.23 возвращалось значение1 и т. Д.

Сейчас я использую вектор, содержащий все три части, key1 / key2 / value, с пользовательским поиском, но кажется, что должна быть более чистая структура.

Редактировать: Спасибо всем. Учитывая, что диапазоны в этом случае должны быть смежными и не перекрывающимися, использование upper_bound будет работать просто отлично. Спасибо за решения класса Range, они также хранятся для дальнейшего использования.

Ответы [ 3 ]

3 голосов
/ 21 апреля 2009
class Range
{
public:
    Range( double a, double b ):
        a_(a), b_(b){}
    bool operator < ( const Range& rhs ) const
    {
        return a_ < rhs.a_ && b_ < rhs.b_;
    }
private:
    double a_;
    double b_;
};
int main()
{
    typedef std::map<Range, double> Ranges;
    Ranges r;

    r[ Range(0, 2) ] = 1;
    r[ Range(2, 5) ] = 2;
    r[ Range(5, 10) ] = 3;

    Ranges::const_iterator it1 = r.find( Range( 2, 2 ) );
    std::cout << it1->second;

    Ranges::const_iterator it2 = r.find( Range( 2, 3 ) );
    std::cout << it2->second;

    Ranges::const_iterator it3 = r.find( Range( 6, 6 ) );
    std::cout << it3->second;

    return 0;
}
2 голосов
/ 21 апреля 2009

Если ваши диапазоны являются смежными и не перекрываются, вы должны использовать std :: map и функцию upper_bound. Или вы можете использовать отсортированный вектор с алгоритмом upper_bound. В любом случае вам нужно только записать самое низкое значение диапазона, при этом верхняя часть диапазона определяется следующим более высоким значением.

Редактировать: Я запутал это, поэтому решил привести пример. При кодировании примера я понял, что вам нужно upper_bound вместо lower_bound. Я всегда путаю этих двоих.

typedef std::map<double, double> MyMap;
MyMap lookup;
lookup.insert(std::make_pair(0.0, dummy_value));
lookup.insert(std::make_pair(2.0, value1));
lookup.insert(std::make_pair(5.0, value2));
lookup.insert(std::make_pair(10.0, value3));
MyMap::iterator p = lookup.upper_bound(1.23);
if (p == lookup.begin() || p == lookup.end())
    ...; // out of bounds
assert(p->second == value1);
1 голос
/ 21 апреля 2009

Как насчет чего-то такого:

#include "stdafx.h"
#include <iostream>
#include <string>
#include <map>
#include <algorithm>
#include <sstream>


class Range
{
public:
    Range(double lower, double upper) : lower_(lower), upper_(upper) {};
    Range(const Range& rhs) : lower_(rhs.lower_), upper_(rhs.upper_) {};
    explicit Range(const double & point) : lower_(point), upper_(point) {};
    Range& operator=(const Range& rhs) 
    { 
        lower_ = rhs.lower_; 
        upper_ = rhs.upper_; 
        return * this; 
    }

    bool operator < (const Range& rhs) const
    {
        return upper_ <= rhs.lower_;
    }

    double lower_, upper_;
};

typedef std::string Thing;
typedef std::map<Range, Thing> Things;


std::string dump(const std::pair<Range,Thing> & p)
{
    stringstream ss;
    ss << "[" << p.first.lower_ << ", " << p.first.upper_ << ") = '" << p.second << "'" << endl;
    return ss.str();
}

int main()
{
    Things things;
    things.insert( std::make_pair(Range(0.0, 5.0), "First") );
    things.insert( std::make_pair(Range(5.0, 10.0), "Second") );
    things.insert( std::make_pair(Range(10.0, 15.0), "Third") );

    transform( things.begin(), things.end(), ostream_iterator<string> (cout,""), dump );

    cout << "--------------------------------------" << endl;

    things[Range(1.5)] = "Revised First";

    transform( things.begin(), things.end(), ostream_iterator<string> (cout,""), dump );


    return 0;
}

... вывод программы:

[0, 5) = 'First'
[5, 10) = 'Second'
[10, 15) = 'Third'
--------------------------------------
[0, 5) = 'Revised First'
[5, 10) = 'Second'
[10, 15) = 'Third'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...