vector how find first and last current value - c++

Task: find first and last current values.
Example:
vector = {1,2,3,1,6,2,1};
need value 1 =>
first index = 0, last = 6; (index/position);
vector<int>::iterator it = find(v.begin(), v.end(), 1);
if (it != v.end())
{
cout << "Element Found" << std::endl;
// Get index of element from iterator
int index = distance(v.begin(), it);
int lastindex = distance(v.end(), it); // bad try to find
cout <<"Index of first element in vector : "<<index<<" last elem ";
// bad code <<lastindex - index <<endl;
}
else
{
cout << "Element Not Found" << std::endl;
}
I found first position but, I can't find last position.
Need help)

You can use reverse iterator to find the last element as follows:
DEMO
int main()
{
std::vector<int> v = {1,2,3,1,6,2,1};
const int currentVal = 1;
const auto itf = std::find(v.cbegin(), v.cend(), currentVal);
const auto itb = std::find(v.crbegin(), v.crend(), currentVal);
if(itf != v.cend()){
std::cout << "front pos: " << std::distance(v.cbegin(), itf) << std::endl;
std::cout << "back pos : " << (v.size() - std::distance(v.crbegin(), itb) - 1) << std::endl;
}
else{
std::cout << currentVal << " is not found." << std::endl;
}
return 0;
}

You can use "rbegin" and "rend" to reverse the list and find the last occurrence by using the same code you have now.
vector = {1,2,3,1,6,2,1};
need value 1 =>
first index = 0, last = 6; (index/position);
vector<int>::iterator it = find(v.begin(), v.end(), 1);
vector<int>::iterator it_reverse = find(v.rbegin(), v.rend(),1);
if (it != v.end() && it_reverse != v.rend())
{
cout << "Element Found" << std::endl;
// Get index of element from iterator
int index = distance(v.begin(), it);
int lastindex = distance(v.rend(), it_reverse); // bad try to find
cout <<"Index of first element in vector : "<<index<<" last elem ";
}
else
{
cout << "Element Not Found" << std::endl;
}

Related

How do I loop through a unordered_map in C++ without auto?

I am trying to loop through an unordered_map, to find if any of its VALUES is greater than 2. But this syntax is wrong
unordered_map<int, int> mp;
for (int i = 0; i < N; i++)
{
mp[arr[i]]++;
}
for (int i = 0; i < mp.size(); i++ ) {
cout << mp[i].second << " " << endl; //mp[i].second is wrong syntax
if (mp[i].second > 2) {
cout << "WRONG";
x = false;
break;
}
}
how can I do this?
It seems that you assumed(incorrectly) that mp[i] is std::pair<int, int> when in fact mp[i] gives you the mapped value which is of type int in your example. This can be seen from std::map::operator[]:
T& operator[]( Key&& key ); (2)
Returns a reference to the value that is mapped to a key equivalent to key, performing an insertion if such key does not already exist.
(emphasis mine)
Method 1
Since you don't want to use auto, you can explicitly write the type std::pair<int, int> in the range-based for loop as shown below:
//---------vvvvvvvvvvvvvvvvvvvvvvvv--------------------->not using auto here as you want
for (const std::pair<const int, int> &pair_elem: mp) {
cout << pair_elem.second << " " << endl;
if (pair_elem.second > 2) {
cout << "WRONG";
//other code here
}
}
Method 2
Note that you can also use std::find_if instead of a for loop as shown below:
auto iter = std::find_if(mp.begin(), mp.end(), [](const std::pair<int,int>& elem)
{ return elem.second > 2;});
if (iter != mp.end())
std::cout << "Greater found ";
else
{
std::cout<<"Greater not found"<<std::endl;
}
Demo
your question is missing a lot of information and literarily , if you searched on web , you would find many ways to loop over unordered_map in C++ , but anyways , here is the edited version of your code with a test case:
#include <iostream>
#include <unordered_map>
using namespace std;
int main() {
const int N = 10;
int arr[N] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
bool x = true;
unordered_map<int, int> mp;
unordered_map<int, int>:: iterator it;
for (int i = 0; i < N; i++)
{
mp[arr[i]]++;
}
mp[9] = 5;
for (it = mp.begin(); it != mp.end(); it++) {
cout << "key is " << it->first << " ,value is " << it->second << " " << endl;
if (it -> second > 2) {
cout << "WRONG";
x = false;
cout << "key is " << it->first << " ,value is " << it->second << " is greater than 2" << endl;
break;
}
}
return 0;
}

Iterating over vectors in C++ and erasing certain elements

Just to provide background, I'm trying to write a function in C++ that takes a vector of ints and a particular int, and removes all of the elements of the vector in place that match the particular int, while returning the number of times it appears.
I'm not asking for help solving the problem. I am stuck trying to figure out why the wrong elements are being erased. Here is the code:
int removeElement(vector<int>& nums, int val) {
int output = 0;
int i = 0;
while (i < nums.size()) {
cout << nums[i] << " " << i << " " << (nums[i] == val) << "\n";
if (nums[i] == val) {
nums.erase(nums.begin() + i);
output+=1;
}
else {
i += 1;
}
}
cout << "---------------\n";
return output;
}
Here is what I'm using to test it:
int main() {
vector<int> firstOne = {3,2,2,3};
cout << removeElement(firstOne,2) << "\n";
firstOne = {3,2,2,3};
cout << removeElement(firstOne,3) << "\n";
}
The output is supposed to be {3,3} and then {2,2} but it's {3,3} twice. Not only that, but the whole thing crashes when I try to test it with a vector with only 2 elements. I suspect there is a gap in my understanding of how vectors work. Can anyone explain to me what I'm doing wrong?
It is better to use erase-remove idiom
int removeElement(vector<int>& nums, int val) {
int output = 0;
int i = 0;
// remove if moves elements "to be removed" in the end
auto newend = std::remove_if(nums.begin(), nums.end(), [&](int element){
cout << element << " " << i << " " << (element == val) << "\n";
i++;
if(element == val) {
output++;
return true; // if true, element will be removed
}
return false; // if false, element will not be removed
});
nums.erase(newend, nums.end());
cout << "---------------\n";
return output;
}
Besides the problems suggested in the comments that you just fixed, your code works fine. You are also not updating output anywhere so the function always returns 0 instead of the number of times the int appears in the passed vector. I edited your function a little and it's good to go:
int removeElement(vector<int>& nums, int val) {
int output = 0;
int i = 0;
while (i < nums.size()) {
cout << nums[i] << " " << i << " " << (nums[i] == val) << "\n";
if (nums[i] == val) {
nums.erase(nums.begin() + i);
output++;
}
else {
i += 1;
}
}
cout << "---------------\n";
return output;
}

Getting strange error while trying to set up an iterator

This is probably a silly error but I can't seem to find what I have done wrong.
The error I am getting is no operator "=" matches these operands.
Here is my code...
void print_words(const map < string, int >& m1) {
map<string, int>::iterator it;
cout << "Number of non-empty words: " << m1.size() << '\n';
int count = 0;
for (it = m1.begin(); it != m1.end(); it++) {
}
}
I get the error in the for loop in the it = m1.begin() statement and I cannot go on to print out the map if I can't iterate through it.
Use a const iterator:
void print_words(const map < string, int >& m1) {
cout << "Number of non-empty words: " << m1.size() << '\n';
int count = 0;
for (map<string, int>::const_iterator it = m1.cbegin(); it != m1.cend(); it++) {
}
}
Use a const_iterator or auto.
void print_words(const map < string, int >& m1) {
cout << "Number of non-empty words: " << m1.size() << '\n';
int count = 0;
for (auto it = m1.cbegin(); it != m1.cend(); it++) {
}
}

How to find all indexes of vector<vector<int>> for the minimum first index

I have a 2-D data vector that is unsorted and contains duplicated elements.
How can I find the minimum and all the indexes with the value?
For example, given data vector<vector<int>> mySol = {{3,1},{1,2},{4,5},{1,3},{1,2}}, I want to find {1,2}, {1,3} and {1,2} which give the minimum value 1 (based on the first element) and indices 2, 3, and 2.
How to improve the following code snippet? For a big data, the following code seems to be slow, because of sort:
vector<vector<int>> mySol = {{3,1},{1,2},{4,5},{1,3},{1,2}};
sort(mySol.begin(), mySol.end());
//print out shortest distance
cout << mySol[0][0] << endl;
//print out the number of shortest paths
int nShortest = 0;
for (int i = 0; i < mySol.size(); i++) {
if (mySol[0][0] == mySol[i][0])
nShortest += 1;
}
cout << nShortest << " ";
//print out y-coordinates of the shortest paths in increasing order
for (int i = 0; i < nShortest; i++) {
cout << mySol[i][1] << " ";
}
You may do the job in linear time:
first find minimum
then iterate on minima.
Something like:
auto cmp = [](const auto& lhs, const auto& rhs) { return lhs[0] < rhs[0]; }
auto minIt = std::min_element(mySol.begin(), mySol.end(), cmp);
auto eqToMin = [&](const auto& value) { return (*minIt)[0] == value[0]; }
for (auto it = minIt; it != mySol.end(); it = std::find_if(it + 1, mySol.end(), eqToMin)) {
std::cout << (*it)[1] << std::endl;
}
Thanks Jarod! Based on Jarod's idea, I modified the code as follows. Use simple min and avoid find_if. This seems to be faster, avoiding sort and finding minimum.
vector<vector<int>> mySol = {{3,1},{1,2},{4,5},{1,3},{1,2}};
auto minIt = std::min(mySol.begin(), mySol.end());
cout << (*minIt)[0] << endl;
int nShortest = 0;
for (auto it = mySol.begin(); it != mySol.end(); ++it) {
if ((*it)[0] == (*minIt)[0]) ++nShortest;
}
cout << nShortest << " ";
for (auto it = mySol.begin(); it != mySol.end(); ++it) {
if ((*it)[0] == (*minIt)[0]) {
cout << (*it)[1] << " ";
}
}

Inserting list elements to vector, getting additional unwanted values C++

In my C++ script, I want to insert some elements of a list into a vector (from the beginning of list to a specific position "it"), and then try to add the vector at the top of the list and keeping the same order of the vector but I get unwanted additional elements in the vector.
Here is my code:
#include <iostream>
#include <iterator>
#include <vector>
#include <list>
int main() {
std::list<int> mylist;
for (int i = 0; i < 10; i++)
mylist.push_back(i * 10);
for (std::list<int>::iterator i = mylist.begin(); i <= mylist.end(); ++i) {
std::cout << *i << ", ";
}
std::cout << std::endl;
std::advance(it, 6);
std::cout << "The 6th element in mylist is: " << *it << std::endl;
// The vector that will contain mylist elements
std::vector<int> intAdeplacer;
intAdeplacer.insert(intAdeplacer.end(), mylist.begin(), it);
std::cout << std::endl;
std::cout << "Nombre d'éléments dans le vecteur : " << intAdeplacer.size() << std::endl;
std::cout << std::endl;
// see the content of the vector
std::cout << "Le vecteur de deplacement contient : " << std::endl;
for (std::vector<int>::const_iterator i = intAdeplacer.begin();
i <= intAdeplacer.end(); ++i) {
std::cout << *i << ", ";
}
I get this output:
Le vecteur de deplacement contient :
0, 10, 20, 30, 40, 134985,
134985 is not wanted..
// Insert in front of the list the values of the vector and keeping the same order of elements in the vector
for (std::vector<int>::const_iterator i = intAdeplacer.end();
i >= intAdeplacer.begin(); --i) {
mylist.push_front(*i);
}
std::cout << std::endl;
std::cout << std::endl;
std::cout << "nouvelle composition de mylist : " << std::endl;
for (std::list<int>::const_iterator j = mylist.begin(); j != mylist.end();
++j) {
std::cout << *j << ", ";
}
std::cout << std::endl;
std::cout << std::endl;
// erasing the added elements from mylist
std::list<int>::iterator debut = mylist.begin();
std::list<int>::iterator fin = mylist.end();
std::advance(fin, 6);
mylist.erase(debut, fin);
for (std::list<int>::iterator j = mylist.begin(); j <= mylist.end(); ++j) {
std::cout << *j << ", ";
}
return 0;
}
If it is an iterator pointing at the 6th element of your list, the following insert() will insert from begin() (included) to it (excluded) into the vector:
intAdeplacer.insert(intAdeplacer.end(), mylist.begin(), it);
So you'll have only 5 elements, from 0 to 40. Unfortunately your printing loop does include the end() of the vector, which is out of range. This is why you get this strange trailing number.
Just correct your loop into:
for (auto i = intAdeplacer.begin(); i != intAdeplacer.end(); ++i) {
std::cout << *i << ", ";
}
Or consider this alternate range-for syntax:
for (auto &element: intAdeplacer) {
std::cout << element << ", ";
}