问题
I have a Python list of dictionaries that I would like to translate to C++.
My list looks more or less like this:
myList = [{"v_A": 5, "v_B": 3}, {"v_A": 1, "v_B":2}, {"v_A":0, "v_B": 0}]
My code is designed such that when I look for e.g. velocities of particle 0, I do:
v = myList[0]["v_"+letter]
where letter
would be a string, "A"
or "B"
, depeding on the output of a sorting function I have. I have found this is the most convenient way to achieve my purpose in Python.
I am trying to translate my code to C++ (being a bit of a newbie) and I don't know how I could keep the "dictionary"-like features (that is, accessing values through a key that can be built concatenating strings) and the benefits the list together like in myList
.
I read this question without much success, being unable to understand: C++ Equivalent of Python List of Dictionaries?
After some research, I thought of a using a vector of unordered maps, but I am unsure on how to define it and work with it. I thought of:
vector< unordered_map <string, int >> myList;
However, I am getting errors all the time. Besides, I don't know how to introduce the values in the dictionaries or access the elements. Am I approaching this from a completely wrong side?
EDIT: I found that if I define and insert the elements piece-wise, it seems to work:
std::vector <unordered_map <string, int> > myList;
unordered_map <string, int> tempMap;
tempMap.insert(std::make_pair("v_A", 10));
myList.push_back(tempMap);
cout << myList[0]["v_A"];
returns correctly 10
. Is there a way to do this more efficient/ in a simpler way?
回答1:
std::vector<std::unordered_map<std::string, int>> dictList; // This is a list of dicts
std::unordered_map<std::string, int> dict; // Here we create a specific dict we want to add to our list of dicts
dict["key"] = 10; // This is how you add (key, value) pair into dict in c++
dictList.push_back(dict); // This is how you add your dict to the list of dicts
回答2:
Inserting in the list can be done much simpler.
At initialization you can do
std::vector<std::unordered_map<std::string, int>> myList {
{{"v_A", 5}, {"v_B", 3}},
{{"v_A", 1}, {"v_B", 2}},
{{"v_A", 0}, {"v_B", 0}}
};
and you can later increase the size of the vector with push_back
:
myList.push_back({{"v_A", 0}, {"v_B", 0}});
or you can add to a dictionary in one of the existing elements the same way as in python:
myList[0]["v_C"] = 12;
You cannot add elements to the vector this way though. (Accessing a vector out-of-bounds causes undefined behavior.)
Elements can be read as in Python with myList[0]["v_C"]
.
You cannot concatenate a character or C style string to a string literal directly with +
as in v = myList[0]["v_"+letter]
(depending on the type of letter
it may compile but will probably not do what you expect it to do). But if you use
using namespace std::string_literals;
after the includes in your .cpp
file, then you can write
v = myList[0]["v_"s+letter];
The s
suffix then causes the string literal to be converted to a std::string
, which provides a +
operator that actually does concatenation.
回答3:
With a std::unordered_map
you can use operator[]
and if the element does not exist it will get inserted into the map.
This is not true for a vector. A vector is a dynamic array and you need to explicitly add elements to it before you can acces the already added elements with operator[]
.
std::vector<std::unordered_map<std::string, int>> myList;
myList[0]; // Invalid since the vector currently is empty.
myList.push_back({}); // Insert a default-constructed element in the vector
myList[0]; // Refers to the first element in the vector, which is a std::unordered_map<std::string, int>
myList[0]["string"] = 1; // This will create the elements if it does not already exist at mentioned above so this works fine
If you know the size you want you vector to have you can use std::vector::resize
or a call to the constructor to set the size.
std::vector<std::unordered_map<std::string, int>> myList(10);
// Create a vector with 10 elements, so [0-9] would be in-bounds.
std::vector<std::unordered_map<std::string, int>> myList;
myList.resize(10); // This will do the same thing but in two steps.
来源:https://stackoverflow.com/questions/59499152/python-list-of-dictionaries-to-c