How to access elements of a pair set in C++ - c++

I have a set. It is of the form set<pair<string,int> > stockSet
I want find if the above set has an entry for a given string that is first element.
Also to find the value of 2nd part of the pair, that is int given the first element of the pair which is string.
I know how to do it with map and also single element set. But I am unable to figure out how to do this, need help with syntax.

You can't figure it out because you can't do this.
The elements in a set are "complete" elements. Just because you see a std::pair in there, and you think that the set contains two elements, it doesn't mean that it is. The set contains a std::pair, a single, complete, element.
If you have another std::pair, somewhere, you can search the set to see if there's an equivalent pair in there. But if you only have half of the object that the set contains, you really can't do it.
The only options I see here are:
iterate over the set manually, until you do or do not find what you're looking for.
If there's a minimum int value you expect to be in there, you can use lower_bound(), passing a std::pair with the minimum value for the int portion, and the string you're search for, and see what lower_bound() digs up.
perhaps reconsider your decision to use a std::set for whatever purpose you're using. Perhaps a std::set, containing a std::pair, isn't really the appropriate container for your requirements.

Related

getting corresponding value in the pair with the second value of the pair, in a set of pairs

suppose I have a set of pairs in c++ as defined below :
std::set<std::pair<std::string, std::string>> s;
and the values stored in the set are for example :
s = {{"Paul", "America"}, {"Joe", "Scotland"}, {"Matt", "Russia"}};
I want to know how can one obtain "America" using only "Paul" in c++17
Input : Paul
Output : America
If you really need this, here are two options
std::find_if for which you'll provide function which checks only first arguments equality, but think about the case when you'll have say (Paul, America) and (Paul, England)
Write a wrapper for std::pair and overload operator< and operator==, first is for allowing to have a set of elements of that type, the second is for finding needed value, as in the first case, checking only the first one in the pair, but again, here you may go in trouble with the same case
Also using the first one you get rid of all goods std::set provides, because that search won't be O(lgn) as you may expect.
I'll recommend to use std::map instead, or if you can have people with same name, std::multimap, which btw has equal_range member function, which will help you to deal with that case.

c++ find vector of element present in the string

I have vector of strings. It contains some names. I need to search whether particular string is present in the vector. Eg: vector of string contains "Name" and "Age". Search string is "NameXYZ". So I have to search whether "NameXYZ" contains any of the vector element. Since one of the vector element is "Name", it should return true. Is there any possibility to achieve this without iterating.
The answer is NO.
It's impossibile to search something in a vector without iterating.
The vector is unorder and unmapped container so you need to iterating to it to find something.
I attach you this link to the cppreference site:
std::vector - cppreference.com
The more complex is answer is SOMETIMES
What you are looking for is something like a hash set. Or for your situation hash map with Key=Name and Value=Age.
This works by defining a function that turns a string into a number, called a hash. When you want to test whether the string is in the list, you calculate what number it has. You then get a list of potential candidates and iterate through those.
If you are lucky, every string has a unique number and you need to test at most one string. You still have to search for the number, but if you use the standard container, you can be certain that it is optimized. Unless you want to spend a long time making your own, it's a simple easy win.
However, be aware that it is very hard to get any search faster than O(Log(N)) complexity. This method is still O(log(N)) complex under the hood, as it has to still search for the hash.

Check if element exist or not

I have a multimap.
std::multimap<CString, CString> NameInsituteMap;
and I have to write function which return true if both name and institute matches otherwise false;
bool InsituteExist( const CString Name, const CString Insitute )
{
}
I can find the key and iterate all the value to compare if Institute exist or not.
I want to know if there is any direct way of doing that instead of looping through all the element and comparing.
I am open to use any other data structure than multimap if that makes things nicer.
Use equal_range from multimap.
Here you have a live example
You can find the sequence elements from the multimap for a given key efficiently. There is no better way to find a particular value from this sequence, than linear search.
std::map<CString, std::set<CString>> would be an alternative data structure, which is also efficient for finding whether a value exists in the set associated with the key. It has a bit different interface though. Instead of simply inserting a value to a key, you must "get" the value set of a key, insert into that set.
If the map aspect of your data structure isn't used otherwise, another simpler alternative is to use std::set<std::pair<CString, Cstring>>. This can be easily used to test if the key-value pair is in the set, but of course lacks other features that the multimap had.

Accessing adjacent elements of a map in c++

Suppose I have a float-integer map m:
m[1.23] = 3
m[1.25] = 34
m[2.65] = 54
m[3.12] = 51
Imagine that I know that there's a mapping between 2.65 and 54, but I don't know about any other mappings.
Is there any way to visit the adjacent mappings without iterating from the beginning or searching using the find function?
In other words: can I directly access the adjacent values by just knowing about a single mapping...such as m[2.65]=54?
UPDATE Perhaps a more important "point" than my answer, brought up by #MattMcNabb:
Floating point keys in std:map
Can I directly access the adjacent values by just knowing about a single mapping (m[2.65]=54)
Yes. std::map is an ordered collection; which is to say that if an operator< exists (more generally, std::less) for the key type you can expect it to have sorted access. In fact--you won't be able to make a map for a key type if it doesn't have this comparison operator available (unless you pass in a predicate function to perform this comparison in the template invocation)
Note there is also a std::unordered_map which is often preferable for cases where you don't need this property of being able to navigate quickly between "adjacent" map entries. However you will need to have std::hash defined in that case. You can still iterate it, but adjacency of items in the iteration won't have anything to do with the sort order of the keys.
UPDATE also due to #MattMcNabb
Is there any way to visit the adjacent mappings without iterating from the beginning or searching using the find function?
You allude to array notation, and the general answer here would be "not really". Which is to say there is no way of saying:
if (not m[2.65][-2]) {
std::cout << "no element 2 steps prior to m[2.65]";
} else {
std::cout << "the element 2 before m[2.65] is " << *m[2.65][-2];
}
While no such notational means exist, the beauty (and perhaps the horror) of C++ is that you could write an augmentation of map that did that. Though people would come after you with torches and pitchforks. Or maybe they'd give you cult status and put your book on the best seller list. It's a fine line--but before you even try, count the letters and sequential consonants in your last name and make sure it's a large number.
What you need to access the ordering is an iterator. And find will get you one; and all the flexibility that it affords.
If you only use the array notation to read or write from a std::map, it's essentially a less-capable convenience layer built above iterators. So unless you build your own class derived from map, you're going to be stuck with the limits of that layer. The notation provides no way to get information about adjacent values...nor does it let you test for whether a key is in the map or not. (With find you can do this by comparing the result of a lookup to end(m) if m is your map.)
Technically speaking, find gives you the same effect as you could get by walking through the iterators front-to-back or back-to-front and comparing, as they are sorted. But that would be slower if you're seeking arbitrary elements. All the containers have a kind of algorithmic complexity guarantee that you can read up on.
When dereferencing an iterator, you will receive a pair whose first element is the key and second element is the value. The value will be mutable, but the key is constant. So you cannot find an element, then navigate to an adjacent element, and alter its key directly...just its value.

std::map<int, int> vs. vector of vector

I need a container to store a value (int) according to two attributes, source (int) and destination (int) i.e. when a source sends something to a destination, I need to store it as an element in a container. The source is identified by a unique int ID (an integer from 0-M), where M is in the tens to hundreds, and so is the destination (0-N). The container will be updated by iterations of another function.
I have been using a vector(vector(int)) which means goes in the order of source(destination(value)). A subsequent process needs to check this container, to see if an element exists in for a particular source, and a particular destination - it will need to differentiate between an empty 'space' and a filled one. The container has the possibility of being very sparse.
The value to be stored CAN be 0 so I haven't had success trying to find out if the space is empty, since I can't seem to do something like container[M][N].empty().
I have no experience with maps, but I have seen another post that suggests a map might be useful, and an std::map<int, int> seems to be similar to a vector<vector<int>>.
To summarise:
Is there a way to check if a specific vector of vector 'space' is empty (since I can't compare it to 0)
Is a std::map<int, int> better for this purpose, and how do I use one?
I need a container to store a value (int) according to two attributes,
source (int) and destination (int)
std::map<std::pair<int, int>, int>
A subsequent process needs to check this container, to see if an
element exists in for a particular source, and a particular
destination - it will need to differentiate between an empty 'space'
and a filled one.
std::map::find
http://www.cplusplus.com/reference/map/map/find/
The container has the possibility of being very sparse.
Use a std::map. The "correct" choice of a container is based on how you need to find things and how you need to insert/delete things. If you want to find things fast, use a map.
First of all, assuming you want an equivalent structure of
vector<vector<int>>
you would want
std::map<int,std::vector<int>>
because for each key in a map, there is one unique value only.
If your sources are indexed very closely sequentially as 0...N, will be doing a lot of look-ups, and few deletions, you should use a vector of vectors.
If your sources have arbitrary IDs that do not closely follow a sequential order or if you are going to do a lot of insertions/deletions, you should use a map<int,vector<int>> - usually implemented by a binary tree.
To check the size of a vector, you use
myvec.size()
To check whether a key exists in a map, you use
mymap.count(ID) //this will return 0 or 1 (we cannot have more than 1 value to a key)
I have used maps for a while and even though I'm nowhere close to an expert, they've been very convenient for me to use for storing and modifying connections between data.
P.S. If there's only up to one destination matching a source, you can proceed with
map<int,int>
Just use the count() method to see whether a key exists before reading it
If you want to keep using a vector but want to add a check for whether the item contains a valid value, look at boost::optional. The type would now be std::vector<std::vector<boost::optional<int>>>.
You can also use a map, but the key into the map needs to be both IDs not just one.
std::map<std::pair<int,int>,int>
Edit: std::pair implements a comparison operator operator< that should be sufficient for use in a map, see http://en.cppreference.com/w/cpp/utility/pair/operator_cmp.