【问题标题】:comparator for nested map嵌套地图的比较器
【发布时间】:2023-02-07 06:27:42
【问题描述】:

我有一张地图,其中包含另一张地图作为值。

外部地图包含字符串名称/自定义类(在本例中我以名称为例),内部地图包含日期时间和值。

我希望 CompareNames 为外部地图运行,CompareDateTime 为内部地图运行。在将比较器传递给结构 A 中的 MyMap 初始值设定项列表时,我能得到一些帮助吗?

#include <iostream>
#include <map>
#include <locale>
#include <string>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/posix_time/posix_time_io.hpp>

enum class ComparePoilicy
{
    custom1,
    custom2
};

struct CompareNames
{
    explicit CompareNames(ComparePoilicy policy)
        : policy(policy)
    {}

    template <typename T>
    bool operator()(const T& lhs, const T& rhs) const
    {
        if (policy == ComparePoilicy::custom1)
        {
            return lhs < rhs;
        }
        else
        {
            return lhs > rhs;
        }
    }

    ComparePoilicy policy;
};

struct CompareDateTime
{
    explicit CompareDateTime(ComparePoilicy policy)
        : policy(policy)
    {}

    template <typename T>
    bool operator()(const T& lhs, const T& rhs) const
    {
        const boost::posix_time::ptime timelhs =
            boost::posix_time::time_from_string(lhs);
        const boost::posix_time::ptime timerhs =
            boost::posix_time::time_from_string(rhs);
        if (policy == ComparePoilicy::custom1)
        {
            return timelhs < timerhs;
        }
        else
        {
            return timelhs > timerhs;
        }
    }

    ComparePoilicy policy;
};

struct A
{
    explicit A(ComparePoilicy dateTime, ComparePoilicy names)
        : MyMap( CompareNames(names), CompareDateTime(dateTime))
    {}
    
    void fillMe()
    {
        MyMap["alpha"]["1981-08-20 08:05:00"] = 1;
        MyMap["alpha"]["1981-08-20 10:05:00"] = 1;
        MyMap["alpha"]["1981-08-20 09:05:00"] = 1;
        MyMap["gamma"]["1981-08-20 08:05:00"] = 1;
        MyMap["gamma"]["1981-08-20 10:05:00"] = 1;
        MyMap["gamma"]["1981-08-20 09:05:00"] = 1;    
        MyMap["beta"]["1981-08-20 08:05:00"] = 1;
        MyMap["beta"]["1981-08-20 10:05:00"] = 1;
        MyMap["beta"]["1981-08-20 09:05:00"] = 1;
    }
    
    void printMe()
    {
        for (auto& item : MyMap)
        {
            for (auto& entry : item.second)
            {
                std::cout << item.first << "  :  " << entry.first << " :  " << entry.second << std::endl;
            }
        }
    }
    
    std::map<std::string, std::map<std::string, int, CompareDateTime>, CompareNames> MyMap;
};


int main()
{
    A test(ComparePoilicy::custom1, ComparePoilicy::custom2);
    test.fillMe();
    test.printMe();

    return 0;
}

colliru链接:http://coliru.stacked-crooked.com/a/2bdfbf3bd96ed17e

我尝试搜索类似的问题,阅读 https://en.cppreference.com/w/cpp/container/map/map 并尝试获得解决方案并使用结构 A 中的初始化列表。

【问题讨论】:

  • 如果我正确阅读了您的代码,您会将两个 comp 对象传递给地图构造函数。没有这样的构造函数。这将是一件愚蠢的事情。您需要将比较器对象传递给内部地图构造的构造。
  • @CaptainGiraffe 我正在寻找正确的方法。我知道我现在在做一些愚蠢的事情,但我无法理解如何解决它 Endgoal 是内部 map(key) 使用一个比较器,外部 map(key) 使用另一个比较器。
  • 好吧,内部映射包含一个比较器对象,无论是 std::less 还是您的自定义比较器。您需要在构建地图之前指定它。 IE。在MyMap["alpha"]["1981-08-20 08:05:00"] = 1;之前最简单的方法可能是为这张地图的地图创建一个包装器。我不认为有一条线可以解决这个问题。这很重要。
  • 我想把它放在结构 A 的初始化列表中。这个例子在实际问题中是虚拟的,地图在运行时被填满。
  • 那么你绝对需要某种包装类/帮助类来巧妙地为你做这件事。地图本身是不够的。

标签: c++ comparator stdmap


【解决方案1】:

简而言之,要使用 std::map::operator[],映射类型必须是默认可构造的,而您的 std::map 使用的比较器不是。

通过避免要求映射类型是默认可构造的成员函数来解决它:

struct A {
    explicit A(ComparePoilicy dateTime, ComparePoilicy names) :
        MyMap(CompareNames(names)),
        m_dateTime(dateTime) // store for when inner maps are to be created
    {}

    // a helper function to insert values with a properly initialized comparator
    void add_one(const std::string& key1, const std::string& key2, int val) {
        if(not MyMap.contains(key1)) {
            MyMap.emplace(key1,
                          std::map<std::string, int, CompareDateTime>
                              (CompareDateTime(m_dateTime)));    
        }
        // using std::map::at is one way to avoid the problem:
        MyMap.at(key1).emplace(key2, val);
    }

    void fillMe() {
        // using the helper function:
        add_one("alpha", "1981-08-20 08:05:00", 1);
        add_one("beta", "1981-08-20 08:05:00", 1);
        add_one("gamma", "1981-08-20 08:05:00", 1);
    }

    std::map<std::string,
             std::map<std::string, int, CompareDateTime>, CompareNames> MyMap;
    // to store the comparator argument for the inner maps:
    ComparePoilicy m_dateTime;
};

Demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多