C++ 将 vector 中的所有元素复制到 map / unordered_map 中的最佳方法
C++ best way to copy all elements from vector into map / unordered_map
使用 C++,如果我想将 vector
转换为 set
或 unordered_set
容器,可以通过以下方式轻松完成:
#include <iostream>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;
int main() {
vector<int> vec {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
// pass
unordered_set<int> uSet(vec.begin(), vec.end());
// pass
set<int> s(vec.begin(), vec.end());
// fail
unordered_map<int, size_t> uMap(vec.begin(), vec.end());
// fail
map<int, size_t> m(vec.begin(), vec.end());
return 0;
}
但是,相同的技术不适用于 map
或 unordered_map
容器。我想知道是否有更好的方法将矢量中的所有元素存储到 map
/ unordered_map
容器中,而不是:
for (int ele : vec) {
++uMap[ele];
}
此外,下面的代码调用了 https://en.cppreference.com/w/cpp/container/unordered_set/unordered_set 中的哪个复制构造函数:
set<int> s(vec.begin(), vec.end());
为什么 https://en.cppreference.com/w/cpp/container/unordered_map/unordered_map 中的类似复制构造函数不可用?
一个map条目有两个"values",而一个vector只有一个。
如果要将矢量元素插入到地图中,则需要决定使用哪个
值将成为键,而哪些将成为值。
这样做的方法是使用成对向量 (vector < pair < K , V >>),它可以像您之前所做的那样用于初始化地图。
让我们看看你的set
构造。
vector<int> vec {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
set<int> s(vec.begin(), vec.end());
这会成功,因为您的 set
的 value_type
是 int
。这不仅仅是方便的术语。一个std::set
定义了一个member type叫value_type
,我是说std::set<int>::value_type
是int
。由于取消引用 vec.begin()
给出了一个可隐式转换为 int
的值(嗯,它 是 int
),此构造成功。
转到 map
,还有一个名为 value_type
的 member type。不过这一次,value_type
不是 int
,因此您提出的构造失败了。 map
的 value_type
是包含键值对的 pair
。也就是说,std::map<int, size_t>::value_type
是 std::pair<const int, size_t>
。由于没有已知的从 int
到任何形式的 std::pair
的转换,您提出的构造失败。
如果您改为从 pair
的 vector
开始工作,您的构建可能会成功。
vector<pair<const int, size_t>> vecp { {1, 2}, {2, 3}, {3, 3}, {4, 4}, {4, 4} };
map<int, size_t> m(vecp.begin(), vecp.end());
这导致 m[1] == 2
、m[2] == 3
、m[3] == 3
和 m[4] == 4
。多余的 {4,4}
被删除,因为这是 map
,而不是 multimap
。 (未指定第一个还是第二个 {4,4}
被丢弃,但丢弃的是额外的那个。)
使用 C++,如果我想将 vector
转换为 set
或 unordered_set
容器,可以通过以下方式轻松完成:
#include <iostream>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;
int main() {
vector<int> vec {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
// pass
unordered_set<int> uSet(vec.begin(), vec.end());
// pass
set<int> s(vec.begin(), vec.end());
// fail
unordered_map<int, size_t> uMap(vec.begin(), vec.end());
// fail
map<int, size_t> m(vec.begin(), vec.end());
return 0;
}
但是,相同的技术不适用于 map
或 unordered_map
容器。我想知道是否有更好的方法将矢量中的所有元素存储到 map
/ unordered_map
容器中,而不是:
for (int ele : vec) {
++uMap[ele];
}
此外,下面的代码调用了 https://en.cppreference.com/w/cpp/container/unordered_set/unordered_set 中的哪个复制构造函数:
set<int> s(vec.begin(), vec.end());
为什么 https://en.cppreference.com/w/cpp/container/unordered_map/unordered_map 中的类似复制构造函数不可用?
一个map条目有两个"values",而一个vector只有一个。 如果要将矢量元素插入到地图中,则需要决定使用哪个 值将成为键,而哪些将成为值。 这样做的方法是使用成对向量 (vector < pair < K , V >>),它可以像您之前所做的那样用于初始化地图。
让我们看看你的set
构造。
vector<int> vec {1, 2, 2, 3, 3, 3, 4, 4, 4, 4}; set<int> s(vec.begin(), vec.end());
这会成功,因为您的 set
的 value_type
是 int
。这不仅仅是方便的术语。一个std::set
定义了一个member type叫value_type
,我是说std::set<int>::value_type
是int
。由于取消引用 vec.begin()
给出了一个可隐式转换为 int
的值(嗯,它 是 int
),此构造成功。
转到 map
,还有一个名为 value_type
的 member type。不过这一次,value_type
不是 int
,因此您提出的构造失败了。 map
的 value_type
是包含键值对的 pair
。也就是说,std::map<int, size_t>::value_type
是 std::pair<const int, size_t>
。由于没有已知的从 int
到任何形式的 std::pair
的转换,您提出的构造失败。
如果您改为从 pair
的 vector
开始工作,您的构建可能会成功。
vector<pair<const int, size_t>> vecp { {1, 2}, {2, 3}, {3, 3}, {4, 4}, {4, 4} };
map<int, size_t> m(vecp.begin(), vecp.end());
这导致 m[1] == 2
、m[2] == 3
、m[3] == 3
和 m[4] == 4
。多余的 {4,4}
被删除,因为这是 map
,而不是 multimap
。 (未指定第一个还是第二个 {4,4}
被丢弃,但丢弃的是额外的那个。)