How to sort a map in OMNeT++? - c++

I didn't find any documentation about map in OMNeT++.
I'm trying to sort a map<int,double> by value, not by key, and erase some data.
I declare the map and iterator like this
std::map<int,double> Dlist;
std::map<int,double>::iterator it;
I tried
sort(Dlist.begin(), Dlist.end());
but there is an error.
Also the iterator doesn't return values
iterator.first
iterator.second

First of all this is a pure C++ related problem, since you are using std::map.
std::sort sorts a container in place, therefore there is no iterator which you can access. Additionally, in the given code the declared iterator is not even used.
Secondly, I strongly doubt that you actually want to sort the map's values. Although this is technically possible, it makes no sense: Sorting std::map using value.
Instead you could copy all values from the map into a std::vector and then sort that vector. See Copy map values to vector in STL.

Related

Speeding up positional access to a std::map

I find myself in a situation where I have to access a std::map by position. Since std::advance(iter, position) is slow af, I want to add a second data structure to speedup this operation.
My idea: Maintain a vector for every key-value pair in the map. Then access the vector by position, vector[position]->second.
When erasing/inserting a new element I obviously have to remove the iterator from the vector. But besides that the iterator-preserving properties of std::map seem to be sufficient.
Question: Is this a good idea?
Alternative: Maintain a vector of map::keys. Then access vector by position an use the key to lookup the value in the map,map[vector[position]]. Is this smarter?
If iteration through the map is your primary performance issue, then you should be using a flat_map (not as of yet part of the standard, but Boost has a decent one). If you don't have one of those, just use a vector<pair> that you keep sorted using the same comparison function you would have used in your map.
You can use std::lower_bound as the equivalent function for being able to find a value by its key. You can also use the iterator returned from std::lower_bound as the position for doing a single-element insertion of a new element. Everything else works just like any other vector; simply keep it sorted and you'll be fine.
std::map search, removal, and insertion operations have logarithmic complexity. The same complexity can be achieved by a sorted std::vector
Don't use a map, but a vector. Keep it sorted by key. Binary search by key is logaritgmic. Access by position is the fastest.
The only drawback is that inserting and removing needs memory reallocation. You may test its performance and consider if it's worth.

Ordered iterator of C++11 unordered map<int, Mytype*>

As the question says, I need to iterate over my map's elements in a certain order, that is, the traditional < order. I thought that by using integers as key, it would have been done automatically, but I was wrong. In fact, when I use a for-each loop like this:
mymap<int, Mytype*> m;
for(auto&x: m){
std::cout << x->first;
}
The keys aren't in order! Why does that happen?It's iterator's fault or maybe it's because of
the hashing function?
EDIT:now I've noticed that if I change the order of insertion it changes the result of the for-each loop too.
EDIT2: I know unordered_map is unordered. But:
"Internally, the elements in the unordered_map are not sorted in any particular order with respect to either their key or mapped values, but organized into buckets depending on their hash values to allow for fast access to individual elements directly by their key values (with a constant average time complexity on average)."(from c++reference)
So I thought I could use a particular Hash function that could give also the order(since keys are int)
From the title of your question I assume that mymap is unordered_map. Well, unordered_map is unordered. The order of entries does not follow from operator< or anything like that, and you may assume that the order is random. The map iterators reflect this internal order.
You can't get order out of an std::unordered_map, you can't really write an ordered iterator for it, unless you really hack the concept.
If you want ordered iteration, either store it in a std::map, which is ordered, but likely slower in accessing, or either copy the contents, or create indexing into a different container, sort it (or use a sorted container like std::map), and use that data. You either re-create this data each time you need it ordered, or keep the two containers in sync. For this the best choice would be to use boost::multi_index_container. Reference: http://www.boost.org/doc/libs/1_55_0b1/libs/multi_index/doc/index.html

C++ map allocator stores items in a vector?

Here is the problem I would like to solve: in C++, iterators for map, multimap, etc are missing two desirable features: (1) they can't be checked at run-time for validity, and (2) there is no operator< defined on them, which means that they can't be used as keys in another associative container. (I don't care whether the operator< has any relationship to key ordering; I just want there to be some < available at least for iterators to the same map.)
Here is a possible solution to this problem: convince map, multimap, etc to store their key/data pairs in a vector, and then have the iterators be a small struct that contain a pointer to the vector itself and a subscript index. Then two iterators, at least for the same container, could be compared (by comparing their subscript indices), and it would be possible to test at run time whether an iterator is valid.
Is this solution achievable in standard C++? In particular, could I define the 'Allocator' for the map class to actually put the items in a vector, and then define the Allocator::pointer type to be the small struct described in the last paragraph? How is the iterator for a map related to the Allocator::pointer type? Does the Allocator::pointer have to be an actual pointer, or can it be anything that supports a dereference operation?
UPDATE 2013-06-11: I'm not understanding the responses. If the (key,data) pairs are stored in a vector, then it is O(1) to obtain the items given the subscript, only slightly worse than if you had a direct pointer, so there is no change in the asymptotics. Why does a responder say map iterators are "not kept around"? The standard says that iterators remain valid as long as the item to which they refer is not deleted. As for the 'real problem': say I use a multimap for a symbol table (variable name->storage location; it is a multimap rather than map because the variables names in an inner scope may shadow variables with the same name), and say now I need a second data structure keyed by variables. The apparently easiest solution is to use as key for the second map an iterator to the specific instance of the variable's name in the first map, which would work if only iterators had an operator<.
I think not.
If you were somehow able to "convince" map to store its pairs in a vector, you would fundamentally change certain (at least two) guarantees on the map:
insert, erase and find would no longer be logarithmic in complexity.
insert would no longer be able to guarantee the validity of unaffected iterators, as the underlying vector would sometimes need to be reallocated.
Taking a step back though, two things suggest to me that you are trying to "solve" the wrong problem.
First, it is unusual to need to have a vector of iterators.
Second, it is unusual to need to check an iterator for validity, as iterators are not generally kept around.
I wonder what the real problem is that you are trying to solve?

How to sort massive map by one value property?

I have a map<std::string, myStruct> I wonder how to sort items in map by int property that is in myStruct.order and if 2 or more of myStruct orders are same throw list of keys (strings) that make map unsortable by that field of myStruct? Is there any fancy way of doing in in C++03 (may be with boost)?
boost has a complete (and complex) functionality in MultiIndex, but if I understand your requirements, it's overkill in this case. A fairly easy way could be to build a list of pointers to myStruct and sort. Then you can easily check for duplicate keys (these became adjacents).
sort should use a functor of type less<const myStruct*>, i.e.
bool compare_orders(const myStruct* a, const myStruct* b) { return a->order < b->order; }
What meaning is there in "sorting" a map? Sure, the map may be internally organized as a BST or something to make access faster, but conceptionally the elements of the map are in no particular order.
Other than that, you CAN supply an ordering method for the keys (because even if you do organize the map in a particular way, it is by the order of the keys, not by that of the values), but not for the values with the third template argument for map.
You can't do this, using std::map - the first in the pair is used for comparing (it's called key). In your case, thestd::string is the key.
You can use std::set< std::pair< std::string, MyStruct > > and then implement operator< for two std::pair< std::string, MyStruct >-s.
Or, you can change the std::map's definition, if it's possible/allowed/suitable/etc. It really depends on what you're trying to do and what you're allowed to do.
Or some other container (that keeps the order of elements, as inserted - like std::list, std::vector, etc.), and then using std::sort or container's sort method, if exists.
I agree with the other answers that it's not clear why you need to sort the map. But you can use a bidirectional map to let you view both myStruct and string as keys.
There's one in boost:
http://www.boost.org/doc/libs/1_48_0/libs/bimap/doc/html/index.html
There's an example here
http://www.boost.org/doc/libs/1_48_0/libs/bimap/doc/html/boost_bimap/examples/simple_bimap.html

Is there any reason that the STL does not provide functions to return an iterator via index?

Is there a reason that the STL does not provide functions to return an iterator into a container via an index?
For example, let's say I wanted to insert an element into a std::list but at the nth position. It appears that I have to retrieve an iterator via something like begin() and add n to that iterator. I'm thinking it would be easier if I could just get an iterator at the nth position with something like, std::list::get_nth_iterator(n).
I suspect I have misunderstood the principles of the STL. Can anyone help explain?
Thanks
BeeBand
You can use advance() from the <iterator> header:
list<foo>::iterator iter = advance(someFooList.begin(), n);
list<foo>::iterator iter = someFooList.begin();
std::advance( iter, n);
If the iterator supports random access (like vector) it'll work quite efficiently, if it only supports increasing (or decreasing) the iterator, like list, it'll work but only as well as can be.
std::list is a linked list. So it does not support random access. To get to the nth position in the list, you have to start at the beginning and move through all the nodes until you arrive at n. This is pretty expensive (O(n)), and thus it's bad to have a method that does not suggest this expense. get_nth_iterator(n) implies getting the iterator that points to the nth node is cheap.
std::vector of course supports this directly with the [] operator, because the datastructure supports random access and so this is very inexpensive for it.
std::list isn't random-access container, so there is no reason for accessing n-th element. if you need this, consider using std::vector instead..
Generally, anything that might be costly is made a bit clumsy, so you won't do it by accident. Using your example, with a container that provides random access iterators it would be simply container.begin()+n, but for an std::list (which provides a forward iterator) you'd need to use list.begin() followed by advance().
If you want to get the Nth iterator, chances are that you just shouldn't be using std::list in the first place. Then again, if you started that sentence at "chances", it would remain nearly as true...