【问题标题】:Printing the key value pairs of a map where the key is a vector in C++打印映射的键值对,其中键是 C++ 中的向量
【发布时间】:2021-01-08 09:20:39
【问题描述】:

我有一个代表图表上点的二维向量。我正在尝试从原点找到这些点之间的欧几里得距离。

这是我的代码:

我的想法是将点映射为向量作为其欧几里得距离的键作为值。我能够做到,但我无法使用键值对打印地图。如何打印地图以查看值

#include <iostream>
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <map>
#include <string>
#include <numeric>
#include <set>
#include <unordered_set>

using namespace std;

int main()
{
    vector<vector<int>> points = { {3,3},{5,-1},{-2,4} };

    unordered_map<vector<int>, double> mp;

    //for loop to find euclidean distance of each data point and then insert into map
    for (int i = 0; i < points.size(); i++)
    {
        int sum = 0;
        vector<int> alpha;  //temporary vector to store the data points 
        
        for (int j = 0; j < points[i].size(); j++)
        {
            sum = sum + (points[i][j] * points[i][j]);
            alpha.push_back(points[i][j]);
        }
        double res = sum;
        res = sqrt(res); //finding sqrt for euclidean distance
        mp.insert({ alpha, res });  //inserting into the map
        alpha.clear();
    }
  
    //Trying to print the map but isn't working
    for (auto itr = mp.begin(); itr != mp.end(); ++itr) {
        cout << itr->first
            << '\t' << itr->second << '\n';
    }

    return 0;
}

错误:C2679 二进制“

【问题讨论】:

  • 请在您的问题中包含错误信息。 std::vector 没有使用 std::cout 打印的重载。您需要遍历向量中的所有元素并一一打印它们(或编写一个为您执行此操作的函数并将向量传递给函数)。
  • 另外,在代码示例中保留#includes 是个好主意。 “保存” 2-3 行代码是一个糟糕的权衡,因为任何想要复制和测试您的代码的人都需要在它工作之前对其进行修改。
  • @super 我修改了我的问题
  • std::vector key IIRC 没有哈希函数

标签: c++ algorithm dictionary data-structures c++17


【解决方案1】:

首先,std::vector 键没有哈希函数,因此您需要使用 std::unordered_map 其他方式:

std::unordered_map<double, std::vector<int>> mp;

你可以有一个单独的函数来打印出std::vector 的元素,因为operator&lt;&lt; 没有为std::vector 类型重载:

template <typename T>
void print_vec(std::vector<T> const& v) {
    bool is_first{ true };
    std::cout << "{ ";
    for (auto const i : v) {
        if (is_first) {
            is_first = false;
            std::cout << i;
        } else {
            std::cout << ", " << i;
        }
    }
    std::cout << " }";
}

然后:

for (auto const& it : mp) {
    cout << it.first << '\t';
    print_vec(it.second);
    cout << '\n';
}

【讨论】:

    【解决方案2】:

    您可以为vectors 定义一个&lt;&lt;,或将其内嵌在您打印的地图中。

    for (auto & [vec, sum] : mp) {
        for (auto & point : vec) {
            std::cout << point << " "
        }
        std::cout << '\t' << sum << '\n';
    }
    

    您还需要为vector 定义一个Hash 以将其用作地图的键。

    template <typename T, typename ElemHash = std::hash<T>>
    struct sequence_hash {
        template <typename C>
        std::size_t operator()(const C & container) {
            std::size_t res = size_hash(container.size());
            for (auto & v : container) { 
                /* some combiner */
                boost::hash_combine(res, elem_hash(v)); 
            }
            return res;
        }
    
    private:
        std::hash<std::size_t> size_hash;
        ElemHash elem_hash;
    };
    

    【讨论】:

    • 不使用boost库可以做到吗
    • @R0bert 是的,你只需要自己写std::size_t hash_combine(std::size_t, std::size_t)。在紧要关头,res ^= elem_hash(v); 并不糟糕。
    猜你喜欢
    • 2019-07-23
    • 2015-09-21
    • 2020-05-31
    • 1970-01-01
    • 1970-01-01
    • 2016-10-05
    • 1970-01-01
    • 2022-11-22
    • 1970-01-01
    相关资源
    最近更新 更多