Iterators over two-dimensional vectors - c++

I have a function that will remove the duplicates in an unsorted vector, keeping it unsorted:
int unsortedRemoveDuplicates(std::vector<int>& numbers)
{
std::set<int> seenNums; //log(n) existence check
auto itr = begin(numbers);
while(itr != end(numbers))
{
if(seenNums.find(*itr) != end(seenNums)) //seen? erase it
itr = numbers.erase(itr); //itr now points to next element
else
{
seenNums.insert(*itr);
itr++;
}
}
return seenNums.size();
}
However I wish to use this for a two-dimensional vector initialised as
vector<vector<int>> numbers;
and have the function remove duplicates from only one row determined by a row number passed into the function.
I've tried changing the iterator itr to
auto itr = begin(numbers[row]);
while(itr != end(numbers[row]))....
where row is pass into the function, but this only creates a seg fault, and so I'm stuck here getting it to iterate over one row. Any suggestions?

Don't over think. Just iterate the outer vector and pass each inner vector to the function.
for (auto& each_row : numbers)
unsortedRemoveDuplicates(each_row);

Related

How to add the results from the iteration to new multimap in c++?

How to insert result into a new multimap?? I am trying to search over dictionary container to find keyword given by the user and I need to iterate over the tempCollector to find distinct elements. But, I can't seem to find a way to store the results in tempCollector.
//current container with all the data
multimap<string, DictionaryItem> dictionaryContainer;
void search(vector<string> input) {
if (dictionaryContainer.empty()) {
cout << "it's empty";
}
int inputSize = input.size();
string tempKeyword = input[0];
//need to copy or insert the value and keys to the tempCollector
multimap<string, DictionaryItem>tempCollector;
//iteration to find keyword; want to store the result in tempCollector
auto its = dictionaryContainer.equal_range(tempKeyword);
for (multimap<string, DictionaryItem>::iterator itr =its.first; itr != its.second; itr++) {
itr->second.print();
}
};
If you want to copy the whole its range:
tempCollector.insert(its.first, its.second);
If you want to copy each element:
for (auto itr =its.first; itr != its.second; itr++) {
if (condition) {
tempCollector.emplace(tempKeyword, itr->second);
//or
tempCollector.insert(*itr);
//or
tempCollector.emplace(tempKeyWord, DictionaryItem(...));
}
}
Keep in mind (multi)map handles pairs of key/values as std::pair<Key,T> (aka value_type).
The multimap::insert method assumes you've already constructed the pair(s) to insert, while multimap::emplace will build them for you.

How to delete particular element of structure type in a list?

how to delete only 5 no element
#include<bits/stdc++.h>
using namespace std;
struct fcfs
{
int process_no;
int burst_time;
};
int main()
{
list<fcfs>lst;
list<fcfs>::iterator it;
struct fcfs pro;
for(int i=1; i<=10; i++)
{
pro.process_no=i;
pro.burst_time=i*10;
lst.push_back(pro);
}
it=lst.begin();
while(it!=lst.end())
{
printf("%d\t%d\n",it->process_no,it->burst_time);
it++;
}
//lst.remove(5);
it=lst.begin();
while(it!=lst.end())
{
printf("%d\t%d\n",it->process_no,it->burst_time);
it++;
}
}
To erase items from list, you need to give the iterator value of 5th element and use erase function to remove, like lst->erase(itr)
And use lst.remove(itr) also to do the same thing. As remove() is an inbuilt function in C++ STL which is declared in header file. remove() is used to remove any specific value/element from the list container. It takes the value which is passed as a parameter and removes all the elements with that value from the list container. And for struct type element removing you need to give the iterator.
For getting the iterator of 5 no element try this,
itr = lst->begin(); // itr is pointing the first element of list
// now increment `itr` four times to get the 5 number element's iterator
for(int i = 0; i < 4; i++) itr++;
// now use `itr` to remove the element which is pointing by itr
lst->remove(itr);
// or erase it
lst->erase(itr);
as from the comment you can use this instead manual loop:
auto itr = std::next(std::begin(lst), 5);

Delete Elements from Vector Inside Loop

I have a vector, words_in_family, of type: vector<vector<string>>. I am trying to delete every element of words_in_family that is not equal to the string vector largest_family, but am having issues and am unsure of why. Any help is appreciated.
for (int i = words_in_family.size() - 1; i >= 0; i--)
{
if (words_in_family[i] != largest_family)
{
words_in_family.erase(words_in_family[i]);
}
}
erase method doesn't take value. Instead use iterator as parameter for erase method:
vector<vector<string>>::iterator it = words_in_family.begin();
for (int i = words_in_family.size() - 1; i >= 0; i--)
{
if (words_in_family[i] != largest_family)
{
words_in_family.erase(it+i);
}
}
iterator erase (iterator position);
iterator erase (iterator first, iterator last);
Note that the iterators for std::vector are random access iterators so you can add/subtract integral values to get other valid iterators.
C++ std::vector erase an element, in your case:
Erase an element from a vector(words_in_family) whose value is equal to largest_family:
std::vector<std::vector<std::string>>::iterator Itr;
for(Itr = Words_in_family.begin(); Itr != Words_in_family.end();)
{
if(*Itr == largest_family)
{
Itr = Words_in_family.erase(Itr);
}
else
{
Itr++;
}
}
words_in_family.erase(words_in_family.begin()+i, words_in_family.begin()+i+1);
erase takes iterator as an argument

operation on 2 dimensional hash map C++

I am currently working on a coding question:
Given an array of strings, return all groups of strings that are anagrams.
For example, Given:
{asch, scah, bva, vba, soa}
return
{ {asch, scah}, {bva, vba}, {soa}}
To solve this question less than O(n^2) time, we should firstly sort each word, and group the sorted words in one set, if the sorted words are the same.
I wanted to use two-dimensional hashmap.
map<string, map<int,string>> container;
to use this two-dimensional hashmap, the first key is the sorted word, the second key is its index in the original sequence, and the value is the original word.
for(int i=0; i<sequence.size();i++)
{
string original_word = sequence[i];
string sorted_word = original_word;
sort(sorted_word.begin(),sorted_word.end());
container[sorted_word][i] = original_word;
}
After this loop, I believe all the anagrams which must have the same sorted_word, will be grouped into the first level of hashmap.
My question is, how should I write the code in order to get the set which has the same sorted_word?
Can I do
for( iterator itr = container.begin(); itr != container.end(); itr++)
{
auto grouped_words = itr.second(); // what is the data type of grouped_word here?
}
correct me if there is anything wrong. Thanks.
I think there's a mistake here:
vector<string, vector<int,string>> container; // ???
As in your question you speak about hash maps, I suppose that you meant:
unordered_map<string, unordered_map<int,string>> container;
In this case, you can use the result as follows:
for( auto itr = container.begin(); itr != container.end(); itr++)
{
auto &grouped_words = itr->second; // prefer a reference
cout << itr->first<<": ";
for (auto &x : grouped_words) {
cout << "\t" << x.first << ":"<< x.second<<endl;
}
}
Here a live demo.
Edit: grouped_words is (here) a reference to an unordered_map<int, string>

Implementing Selection Sort for Linked Lists

I am trying to implement a selection sort algorithm that will work with linked lists and will use iterators to scrool through them. The selection sort algorithm is the following: for each element of the list except the last one(let's call it K), it will seek out the smallest on from the position we are currently on(so it will start from K until the last element). After that it will swap K and the smallest element.
I think that my mistake is in the first for loop; I am very unsure that --a.end() is the pre-last element. I get some output, though it is wrong.
#include <iostream>
#include <list>
using namespace std;
void sort_list(list<int>& a)
{
//from the first until the pre-last element
for(list<int> :: iterator itr = a.begin(); itr != (--a.end()); ++itr)
{
int smallest = *itr;
//get smallest element after current index
list<int> :: iterator itr2 =itr;
++itr2;
for(; itr2 != a.end(); ++itr2)
{
if (smallest > *itr2)
{
smallest = *itr2;
}
}
//swap smallest and current index
int tmp = *itr;
*itr = smallest;
smallest = tmp;
}
}
int main()
{
//create a list and some elements
list<int> listi;
listi.push_back(5);
listi.push_back(4);
listi.push_back(3);
listi.push_back(2);
listi.push_back(1);
// sort the list
sort_list(listi);
//print all of the elements
for(list<int> :: iterator itr = listi.begin(); itr != listi.end(); ++itr)
{
cout << *itr << endl;
}
return 0;
}
When you do itr2 = ++itr you also change the value of itr, so instead you should do something like
list<int> :: iterator itr2 = itr;
for(++itr2; itr2 != a.end(); ++itr2) {
...
}
Furthermore, you have to keep a pointer to the smallest element, if you want to swap it later, like this:
int* smallest = &(*itr);
This also requires some other changes, you can find a working example of your code here.
The problem is you spoil itr while initializing itr2.