4

Boost.ICLには、 とのinterval_map2 種類の動作が+=ありinsertます。どちらも異なるコンテキストで役立ちます。1 つ目は、既存の 2 つの間隔の共通部分の値を合計します。2 つ目は、以前に割り当てられていない間隔でのみ新しい値を導入するだけです(以前に割り当てられた間隔では値が保持されます)。

(1.,2.)->1 , (2.5,3.)->3, (3.,5.)->2ただし、以下の例では、望ましくない間隔マップを取得する代わりに、目的の を取得するなど、微妙に異なる動作が必要(1.,2.)->1 , (2.5,5.)->3です。

つまり、新しく挿入された値が古い値を置き換えるということですか? その置換動作interval_mapを取得するにはどうすれば宣言できますか?

#include<boost/icl/interval_map.hpp>
int main(){
    boost::icl::interval_map<double, int> joined_map;
    joined_map.insert( std::make_pair(
        boost::icl::interval<double>::open(1., 2.),
        1
    ));
    joined_map.insert( std::make_pair(
        boost::icl::interval<double>::open(3., 5.),
        2
    ));
    joined_map.insert( std::make_pair(
        boost::icl::interval<double>::open(2.5, 5.),
        3
    )); // this line doesn't replace the old value 2, it keeps it.
}

おまけ:それはboost::icl::mapすべきことですか?どうやって使うの?


編集 1:これは、C++11 を使用したより明示的で単純化されたサンプル コードです。

#include<boost/icl/interval_map.hpp>
#include<iostream>

namespace icl = boost::icl;
using interval = icl::interval<double>;

int main(){
    icl::interval_map<double, int> joined_map;

    joined_map.insert({interval::open(1., 2.), 1});
    joined_map.insert({interval::open(3., 5.), 2});
    joined_map.insert({interval::open(2.5, 5.), 3}); 
    // ^^^^ this line doesn't replace the old value 2! it keeps it.
    for(auto e: joined_map) std::cout << e.first <<' '<< e.second <<'\n';
    // prints: (1,2) 1 \\ (2.5,3] 3 \\ (3,5) 2
    // desired: (1,2) 1 \\ (2.5,5] 3  // value 2 gone
}

編集 2: @JorgeBellon の回答に基づく完全なソリューション:

#include<boost/icl/interval_map.hpp>
#include<iostream>

namespace icl = boost::icl;

template <class Type>
struct inplace_replace{// : icl::identity_based_inplace_combine<Type>{
    using first_argument_type = Type;
    void operator()(Type& object, Type const& operand) const{object = operand;}
};

using interval = icl::interval<double>;

int main(){

    icl::interval_map<
        double, int,
        icl::partial_enricher,   // Unmapped intervals have unkown value;
                                 // store identity values
        std::less             ,  // Comparator
        inplace_replace     //,  // Combination operator // IMPORTANT!!
    //  icl::inplace_erasure//,  // Extraction operator
    //  closed_interval<unsigned, std::less> // Interval type
    > joined_map;
    joined_map.add({interval::open(1. , 2.), 1}); // or joined_map+=std::make_pair(...)
    joined_map.add({interval::open(3. , 5.), 2}); // IMPORTANT: USE add, NOT insert!!
    joined_map.add({interval::open(2.5, 5.), 3}); 
    // ^^^^ this line now replaces the old value 2
    for(auto e: joined_map) std::cout << e.first <<' '<< e.second <<'\n';
    // prints: (1,2) 1 \\ (2.5,5] 3  // value 2 gone
}
4

2 に答える 2

3

間隔マップのテンプレート パラメーターの 1 つは、組み合わせ演算子の型です。std::set典型的な例は、値としてまたは類似のものを使用してマップ上で構成され、操作として追加または同一性(既存の値を保持) を使用します。

上書きの例はデフォルトでは存在しないため、自分で作成してマップに渡すことができます。

#include <boost/icl/interval_map.hpp>

using namespace boost::icl;

// interval_map combiner functor: assigns new value if key exists
template <class Type>
struct inplace_replace : identity_based_inplace_combine<Type> {
  void operator()(Type &object, const Type &operand) const {
    object = operand;
  }
};

template<>
inline std::string unary_template_to_string<inplace_replace>::apply() {
  return "=";
}

// When adding, if interval exists, replaces value.
// When subtracting, if interval exists, removes value.
using ival_map =
    interval_map<unsigned,         // Key
                 unsigned,         // Value
                 partial_enricher, // Unmapped intervals have unkown value; store identity values
                 std::less,        // Comparator
                 inplace_replace,  // Combination operator
                 inplace_erasure,  // Extraction operator
                 >;

完全な例を参照してください: https://ideone.com/C49bDM

identity_based_inplace_combine<Type>編集: ( boost/icl/functors.hpp)から派生すると、次のことが行われます。

  • first_argument_typesecond_argument_typeおよびを定義しresult_typeます。
  • そのタイプの値を作成するために使用されますidentity_element(静的関数)。たとえば、セットのアイデンティティ値は空のセットであり、整数の場合はそうです0(合計を行うときに役立ちます)などです。

partial_enricherマップがまたはの場合は、必須ではありませんtotal_enricher。この場合、マップには ID 値を含む任意の値のエントリが含まれるためです。absorberその場合、マップは間隔をドロップできるかどうかを知る必要があるため、タイプに必要になります。

別の方法:

// interval_map combiner functor: assigns new value if key exists
template <class Type>
struct inplace_replace {
  typedef void result_type;
  typedef Type& first_argument_type;
  typedef const Type& second_argument_type;

  void operator()(Type &object, const Type &operand) const {
    object = operand;
  }
};

std::binary_function注: 古いブースト ICL 実装は、これらの typedef を使用する代わりに派生します。残念ながら、これは C++11 では非推奨であり、C++17 では削除されているため、独自のコードでは使用しないようにします。最新バージョンは、上記のスニペットのようなファンクターを実装しています。

同じ例: https://ideone.com/lMLEDw

于 2019-10-28T12:06:04.203 に答える