I'm trying to dynamically add elements to a vector that is contained within a map, to store multiple arrays of "Particle" objects that are mapped to different ids. I'm new to the language and so I'm having trouble understanding if this can only be done with iterators? In this case it feels like overkill. Is it possible to directly access a vector inside a map? Since I can access the map elements by key, and because there is only one vector per key, it seems like it should be possible. I don't really have exact code as an example but it would look something like this:
int currentId = 1;
map <int, vector<Particle> > particleMap;
Particle p;
particleMap[currentId] <access to vector somehow here?> push_back(p);
I'm sure I'm missing some larger concept here, but I find myself needing this type of data structure a lot, so it would be great to know the proper way to access these kinds of "tables."
particleMap[currentId].push_back(p);
will work just fine.
There is only one vector per id; this is what you are referring to with particleMap[currentId]. Then you just continue with the expression as if you were writing myVector.push_back(p).
Related
I was looking into separate chaining using hash_map and that is kind of what I need but not entirely. A hash_map will automatically delete duplicate values even in a chain. I dont want that.
Consider I have a vector of size 4. I want to basically attach a linked list to each one of the indexes of the vector. the linked list can have duplicate elements as well.
I researched about this but could not find a STL for this. Is there a way to do this?
I want to do this to create a database table. I have a vector of size 4. The 4 spots are columns in the table and the linked list attached to each index are the rows for the table. Hope this makes sense.
It sounds like you just want a Vector of Lists. Please specify the type for the data that you want to store in your table. The declaration will depend on that... If you're storing ints, it would look like this:
std::vector<std::list<int> > vecOfLists;
You mean something like this?
std::vector<std::list<std::string> > > myweirdlist;
Then you can add more lists to myweirdlist. And myweirdlist[0] for example will be a linked list which you can operate one.
Encapsulate the row in a class. Store a vector of objects of that class.
If you have a lot of deletions as well as insertions, maybe a list would be better, instead of the vector.
struct MyRecord {
// fields
};
std::vector<MyRecord> myRecordTable;
What are the advantages and disadvantages of the following ways of making a map that is intended to represent a two dimensional grid. The grid should be able to be filled in at any point, without allocating memory for the whole thing, which is why I didn't just use a 2d array.
std::map<int, std::map<int, Tile*>* >* tiles;
std::map<std::pair<int, int>, Tile*>* tiles;
Or if you have another better idea let me know. I'm sorry if this is a question that gets asked alot.
It's (obviously) a different data structure and depends on how you access it.
The first one is more like a 2-level tree structure. Map x-coordinates to several y-coordinates to several tiles again. This may sound a little inappropriate to your problem.
The second one does not allow you to get all elements for a specific x-coordinate (or however you may call it). You may not need that anyway?
If you need to map (x,y) coordinates to tile, the 2nd approach might be ok.
Why not use a vector of a vector , std::vector< std::vector > ?
It would be better unless your grid is sparse (not every element in the grid has a Tile), and you want to conserve memory. Access time using a vector would be much better if speed is the issue since std::map uses tress as the underlying structure.
I have a settings which are stored in std::map. For example, there is WorldTime key with value which updates each main cycle iteration. I don't want to read it from map when I do need (it's also processed each frame), I think it's not fast at all. So, can I get pointer to the map's value and access it? The code is:
std::map<std::string, int> mSettings;
// Somewhere in cycle:
mSettings["WorldTime"] += 10; // ms
// Somewhere in another place, also called in cycle
DrawText(mSettings["WorldTime"]); // Is slow to call each frame
So the idea is something like:
int *time = &mSettings["WorldTime"];
// In cycle:
DrawText(&time);
How wrong is it? Should I do something like that?
Best use a reference:
int & time = mSettings["WorldTime"];
If the key doesn't already exist, the []-access will create the element (and value-initialize the mapped value, i.e. 0 for an int). Alternatively (if the key already exists):
int & time = *mSettings.find("WorldTime");
As an aside: if you have hundreds of thousands of string keys or use lookup by string key a lot, you might find that an std::unordered_map<std::string, int> gives better results (but always profile before deciding). The two maps have virtually identical interfaces for your purpose.
According to this answer on StackOverflow, it's perfectly OK to store a pointer to a map element as it will not be invalidated until you delete the element (see note 3).
If you're worried so much about performance then why are you using strings for keys? What if you had an enum? Like this:
enum Settings
{
WorldTime,
...
};
Then your map would be using ints for keys rather than strings. It has to do comparisons between the keys because I believe std::map is implemented as a balanced tree. Comparisons between ints are much faster than comparisons between strings.
Furthermore, if you're using an enum for keys, you can just use an array, because an enum IS essentially a map from some sort of symbol (ie. WorldTime) to an integer, starting at zero. So then do this:
enum Settings
{
WorldTime,
...
NumSettings
};
And then declare your mSettings as an array:
int mSettings[NumSettings];
Which has faster lookup time compared to a std::map. Reference like this then:
DrawText(mSettings[WorldTime]);
Since you're basically just accessing a value in an array rather than accessing a map this is going to be a lot faster and you don't have to worry about the pointer/reference hack you were trying to do in the first place.
I need to insert values into std::map (or it's equivalent) to any free position and then get it's key (to remove/modify later). Something like:
std::map<int, std::string> myMap;
const int key = myMap.insert("hello");
Is it possibly to do so with std::map or is there some appropriate container for that?
Thank you.
In addition to using a set, you can keep a list of allocated (or free)
keys, and find a new key before inserting. For a map indexed by
int, you can simply take the last element, and increment its key. But
I rather think I'd go with a simple std::vector; if deletion isn't
supported, you can do something simple like:
int key = myVector.size();
myVector.push_back( newEntry );
If you need to support deletions, then using a vector of some sort of
"maybe" type (boost::optional, etc.—you probably already have
one in your toolbox, maybe under the name of Fallible or Maybe) might be
appropriate. Depending on use patterns (number of deletions compared to
total entries, etc.), you may want to search the vector in order to
reuse entries. If your really ambitious, you could keep a bitmap of the
free entries, setting a bit each time you delete and entry, and
resetting it whenever you reuse the space.
You can add object to an std::set, and then later put the whole set into a map. But no, you can't put a value into a map without a key.
The closest thing to what you're trying to do is probably
myMap[myMap.size()] = "some string";
The only advantage this has over std::set is that you can pass the integer indexes around to other modules without them needing to know the type of std::set<Foo>::iterator or similar.
It is impossible. Such an operation would require intricate knowledge of the key type to know which keys are available. For example, std::map would have to increment int values for int maps or append to strings for string maps.
You could use a std::set and drop keying altogether.
If you want to achieve something similar to automatically generated primary keys in SQL databases than you can maintain a counter and use it to generate a unique key. But perhaps std::set is what you really need.
When calling boost::get on a graph, the return type is boost::associative_property_map<Graph, PropertyType>. I'd like to get a copy of this map, and I'd like to store it in a boost::vector_property_map. However, they are not compatible enough to allow simply assigning to the vector map. Looking at the source of property_map, it seems boost::associative_property_map does not have any access methods at all (the vector variety at least exposes "storage iterators").
Is there a way? Or do I have to find the keys somehow and loop over them?
I am sorry, but simply using boost::associative_property_map, you won't be able to retrieve iterators over contained items. You must use an alternate way to iterate over them -- iterate over edges or vertices, i guess, and put them into a boost::vector_property_map.
But if you have to do that, it means you are deconstructing the whole idea of having the common interface that property maps provide. Can't you templatize the algorithm which currently needs vector_property_map to have it accept other property_map types ?