如何在 C++ 中访问 map<string, vector<int>> 的值?
How to access the values of a map<string, vector<int>> in C++?
我正在研究我的遗传算法版本来解决 C++ 中的背包问题。我有一个字符串到向量的映射,比如
map<string, vector<int>> objects
{
{"Object 1", {7, 20, 15}},
{"Object 2", {3, 50, 10}},
{"Object 3", {5, 80, 12}},
{"Object 4", {4, 80, 8}},
{"Object 5", {2, 40, 11}}
};
和一个向量的向量
vector<vector<int>> population;
我将在哪里存储信息,例如
population[0] = {0, 0, 1, 1, 0};
population[1] = {1, 0, 0, 0, 1};
population[2] = {1, 0, 1, 0, 1};
...
每个向量称为一个individual
,给定个体的每个元素表示对应对象的存在(1
)或不存在(0
)。因此,例如,第三个人 (population[2]
) 有 Object 1
、Object 3
和 Object 5
.
我想做的是编写一个函数,它将接收来自 population
的索引和 return 来自 objects
的相应值的总和。在 population[2]
的情况下,我想要另一个包含 {14, 140, 38}
(7+5+2, 20+80+40, 15+12+11
) 的向量。
但我很难访问 objects
地图的值。
map<string, vector<int>> objects {/*...*/}
vector<vector<int>> population;
void initializePopulation() {/*...*/}
void getScore(vector<int> individual, vector<int>& sum)
{
for(int i = 0; i < 3; i++)
{
sum.push_back(0);
for(int j = 0; j < 5; j++)
{
if(individual[j] == 1)
{
sum[i] += ???;
}
}
}
int main()
{
/*...*/
initializePopulation();
vector<int> sum;
getScore(population[2], sum);
}
因此,如您所见,我不确定如何继续 sum[i]
。有什么建议么?我的 C++ 不是很流利,所以更详细的答案将不胜感激!
对于向量的向量和地图,您可以使用 for each 循环!
当您的地图充满价值
for(auto x: objects){
cout<<x.first<<" "<<x.second<<endl;
}
这将在映射中打印键值对,中间有 space!
在这个问题中,您还必须在地图中迭代值(即第二个)!
{"Object 1", {7, 20, 15}}
{"Object 2", {3, 50, 10}}
{"Object 3", {5, 80, 12}}
{"Object 4", {4, 80, 8}}}
{"Object 5", {2, 40, 11}}
对于这样的事情,下面的代码应该可以工作:
for(auto x: objects){
cout<<x.first<<" ";
for(auto y: x.second){
cout<<y<<" ";
}
cout<<endl;
}
对于向量的向量,你可以使用相同的概念!
尝试将 Object 1, Object 2, ....
重命名为 1,2, ....
这将允许您使用 for 循环中的 j 访问 map 中的值!
对于更简化的版本,请考虑使用此原型,因为您使用的是人口和遗传等词,我认为您的数据非常庞大,所以您最好使用 const 参考 在传递数据时(const&,它们不会被复制并且将变为只读)。全局变量通常不是一个好主意。
void getScore(map<string, vector<int>> const& objects, vector<int> const& individual, vector<int>& sum)
{
// iterate over each object for the individual
for(int i = 0; i < 5; i++)
{
// are you sure you want sum as {14, 140, 38} (7+5+2, 20+80+40, 15+12+11)
// not {14,0, 140,0, 38} (7+5+2, 0, 20+80+40, 0, 15+12+11)
// use else part for later
if(individual[i] == 1)
{
// compute sum for each object
// retrieve object vector
auto it = objects.find("KEY"); // KEY generation discussed later
if(it!=objects.end()){ // validate key :::: important
vector<int> ob = objects["KEY"]; //it->second
sum.push_back(std::accumulate(ob.begin(),ob.end(),0) ); // https://www.cplusplus.com/reference/numeric/accumulate/
}
} /*else {
sum.push_back(0);
}*/
}
}
密钥生成:
1).生成“对象 1”:
string key = "Object " + to_string(i+1)
auto it = objects.find(key);
2).建议:
使用整数作为键
要么
使用像
这样的枚举
enum ObjList{
OBJECT_1,
OBJECT_2,
OBJECT_3
}
auto it = objects.find(i); //mind your indexes
希望对您有所帮助,编码愉快 XD
我认为用一些线性代数你的问题有一个简单的解决方案:事实上,如果你将与你的对象相关的数值数据存储到矩阵 A 中,那么对于每个 population
向量 p
你想要的结果只是 p^T A (或等效地,A^T p),其中 ^T 表示矩阵或向量的 transpose。
如果您不打算使用任何线性代数库,您可以自己实现 scalar product。下面是实现上述想法的代码。
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <numeric>
std::vector<int> SP(std::vector<std::vector<int>> const &M, std::vector<int> const &P){
std::vector<int> sums(3,0);
// perform p^T * A operation
for (int j=0;j<3;j++)
for (int i=0;i<5;i++)
sums[j] += M[i][j] * P[i];
return sums;
}
int main(){
std::map<std::string, std::vector<int>> objects {
{"Object 1", {7, 20, 15}},
{"Object 2", {3, 50, 10}},
{"Object 3", {5, 80, 12}},
{"Object 4", {4, 80, 8}},
{"Object 5", {2, 40, 11}}
};
std::vector<std::vector<int>> population(3);
population[0] = {0, 0, 1, 1, 0};
population[1] = {1, 0, 0, 0, 1};
population[2] = {1, 0, 1, 0, 1};
std::vector<std::vector<int>> A;
// Extract the numerical data from the map
for (auto const& [key, val] : objects)
A.push_back(val);
// vector in which the desired values are stored for the 3rd element of the population
std::vector<int> s = SP(A,population[2]);
// Just for checking
for (int it=0; it<s.size(); it++)
std::cout << s[it] << std::endl;
return 0;
}
我正在研究我的遗传算法版本来解决 C++ 中的背包问题。我有一个字符串到向量的映射,比如
map<string, vector<int>> objects
{
{"Object 1", {7, 20, 15}},
{"Object 2", {3, 50, 10}},
{"Object 3", {5, 80, 12}},
{"Object 4", {4, 80, 8}},
{"Object 5", {2, 40, 11}}
};
和一个向量的向量
vector<vector<int>> population;
我将在哪里存储信息,例如
population[0] = {0, 0, 1, 1, 0};
population[1] = {1, 0, 0, 0, 1};
population[2] = {1, 0, 1, 0, 1};
...
每个向量称为一个individual
,给定个体的每个元素表示对应对象的存在(1
)或不存在(0
)。因此,例如,第三个人 (population[2]
) 有 Object 1
、Object 3
和 Object 5
.
我想做的是编写一个函数,它将接收来自 population
的索引和 return 来自 objects
的相应值的总和。在 population[2]
的情况下,我想要另一个包含 {14, 140, 38}
(7+5+2, 20+80+40, 15+12+11
) 的向量。
但我很难访问 objects
地图的值。
map<string, vector<int>> objects {/*...*/}
vector<vector<int>> population;
void initializePopulation() {/*...*/}
void getScore(vector<int> individual, vector<int>& sum)
{
for(int i = 0; i < 3; i++)
{
sum.push_back(0);
for(int j = 0; j < 5; j++)
{
if(individual[j] == 1)
{
sum[i] += ???;
}
}
}
int main()
{
/*...*/
initializePopulation();
vector<int> sum;
getScore(population[2], sum);
}
因此,如您所见,我不确定如何继续 sum[i]
。有什么建议么?我的 C++ 不是很流利,所以更详细的答案将不胜感激!
对于向量的向量和地图,您可以使用 for each 循环! 当您的地图充满价值
for(auto x: objects){
cout<<x.first<<" "<<x.second<<endl;
}
这将在映射中打印键值对,中间有 space!
在这个问题中,您还必须在地图中迭代值(即第二个)!
{"Object 1", {7, 20, 15}}
{"Object 2", {3, 50, 10}}
{"Object 3", {5, 80, 12}}
{"Object 4", {4, 80, 8}}}
{"Object 5", {2, 40, 11}}
对于这样的事情,下面的代码应该可以工作:
for(auto x: objects){
cout<<x.first<<" ";
for(auto y: x.second){
cout<<y<<" ";
}
cout<<endl;
}
对于向量的向量,你可以使用相同的概念!
尝试将 Object 1, Object 2, ....
重命名为 1,2, ....
这将允许您使用 for 循环中的 j 访问 map 中的值!
对于更简化的版本,请考虑使用此原型,因为您使用的是人口和遗传等词,我认为您的数据非常庞大,所以您最好使用 const 参考 在传递数据时(const&,它们不会被复制并且将变为只读)。全局变量通常不是一个好主意。
void getScore(map<string, vector<int>> const& objects, vector<int> const& individual, vector<int>& sum)
{
// iterate over each object for the individual
for(int i = 0; i < 5; i++)
{
// are you sure you want sum as {14, 140, 38} (7+5+2, 20+80+40, 15+12+11)
// not {14,0, 140,0, 38} (7+5+2, 0, 20+80+40, 0, 15+12+11)
// use else part for later
if(individual[i] == 1)
{
// compute sum for each object
// retrieve object vector
auto it = objects.find("KEY"); // KEY generation discussed later
if(it!=objects.end()){ // validate key :::: important
vector<int> ob = objects["KEY"]; //it->second
sum.push_back(std::accumulate(ob.begin(),ob.end(),0) ); // https://www.cplusplus.com/reference/numeric/accumulate/
}
} /*else {
sum.push_back(0);
}*/
}
}
密钥生成:
1).生成“对象 1”:
string key = "Object " + to_string(i+1)
auto it = objects.find(key);
2).建议: 使用整数作为键 要么 使用像
这样的枚举enum ObjList{
OBJECT_1,
OBJECT_2,
OBJECT_3
}
auto it = objects.find(i); //mind your indexes
希望对您有所帮助,编码愉快 XD
我认为用一些线性代数你的问题有一个简单的解决方案:事实上,如果你将与你的对象相关的数值数据存储到矩阵 A 中,那么对于每个 population
向量 p
你想要的结果只是 p^T A (或等效地,A^T p),其中 ^T 表示矩阵或向量的 transpose。
如果您不打算使用任何线性代数库,您可以自己实现 scalar product。下面是实现上述想法的代码。
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <numeric>
std::vector<int> SP(std::vector<std::vector<int>> const &M, std::vector<int> const &P){
std::vector<int> sums(3,0);
// perform p^T * A operation
for (int j=0;j<3;j++)
for (int i=0;i<5;i++)
sums[j] += M[i][j] * P[i];
return sums;
}
int main(){
std::map<std::string, std::vector<int>> objects {
{"Object 1", {7, 20, 15}},
{"Object 2", {3, 50, 10}},
{"Object 3", {5, 80, 12}},
{"Object 4", {4, 80, 8}},
{"Object 5", {2, 40, 11}}
};
std::vector<std::vector<int>> population(3);
population[0] = {0, 0, 1, 1, 0};
population[1] = {1, 0, 0, 0, 1};
population[2] = {1, 0, 1, 0, 1};
std::vector<std::vector<int>> A;
// Extract the numerical data from the map
for (auto const& [key, val] : objects)
A.push_back(val);
// vector in which the desired values are stored for the 3rd element of the population
std::vector<int> s = SP(A,population[2]);
// Just for checking
for (int it=0; it<s.size(); it++)
std::cout << s[it] << std::endl;
return 0;
}