Adding to a set while iterating (C++) - c++11

If I have the following code (assume the set is unordered set):
mySet.insert(0);
int i = 1;
for(auto itr = mySet.begin(); itr != mySet.end(); ++itr){
mySet.insert(i);
i++;
}
It would end up updating the set as it iterates and result in an endless loop. If I wanted instead to iterate over only the elements in the set before modifying, how could I ensure that the addition of new elements does not affect the iteartion?
If I were to do this with a list, the code would look like :
myList.push_front(0);
int i = 1;
for(auto itr = myList.begin(); itr != myList.end(); ++itr){
myList.push_front(i);
i++;
}
But there is not push_front method for sets (makes sense), but I wanted to do this while taking advantage of the fact that sets only contain unique elements.

You can't.
Possible workarounds:
Create a copy of the set, iterate over the copy.
Create a temporary set that you add new values to, then after the iteration add all values from the temporary set to your original set.

Related

Cannot invoke splice(int, int) on the array type int[][]

I have a short code which I can't seem to figure out. The biggest problem which I have is that I don't understand the error and cannot seem to find how I can change the type of my array.
int [][] spawnLocatiesCoins = new int [20][2];
void collectenVanCoins () {
if (gameState == 1) {
for (int i = 0; i<10; i++) {
if (key == 's' && dist(spawnLocatiesCoins[i][0], spawnLocatiesCoins[i][1], xPosPlayer1, yPosPlayer1) < 20) {
println("catch" + i);
score++;
spawnLocatiesCoins.splice(i, 1);
}
}
}
}
What I am trying to do is remove the spawnLocationsCoins[i] from my array. The error message which I get here is Cannot invoke splice(int, int) on the array type int[][]. I have tried several different approaches for the splice method. I have also tried using the remove method with no result.
Could someone explain to me how I can remove an item from a int [][] array.
You are probably trying to use Processing splice function, however, that doesn't do what you want ("Inserts a value or an array of values into an existing array").
I'd say you are best off using an ArrayList instead of an array, where you can then just use the .remove function like this:
list.remove(index);
Because you want to store 2 values (x and y), you could make an ArrayList of int arrays
ArrayList<int[]> spawnLocatiesCoins = new ArrayList<int[]>();
You can add values like this:
spawnLocatiesCoins.add(new int[]{x_value, y_value});
And access them like this:
spawnLocatiesCoins.get(index)[index_in_the_array];
You could also use PVectors (variables that can store 2/3 values (depending on whether you are making a 3D program)) instead of arrays, but you probably don't need them at this point.

Insert a map into other map with a unique type key

hello guys i am new to maps in C++ i am having a question regarding copying a particular type map to another map of same kind the details are shown below
I initially declared a map like this
map<string,int> objmap,obj_porcess ;
for(int i = 0; i < 10]; i++) {
obj_process[to_string(i)]=i+10//some processing the to_string is just in case but i have strings with names for all 10 values
}
like
obj_process["today"]=1;
obj_process["yesterday"]=-1;
obj_process["tommorow"]=2;
now i want to define some thing like this just my key word should be added with the process and remaining all can be same for all the keys from obj_process
objmap["process_"+"today"] = obj_process["today"];
instead of defining all 10 can i have a simple code cause in here i took an example of 10 but i have like 200 set of different strings in the key of map
I think this is what you need:
map<string,int> objmap;
map<string,int> obj_porcess;
//
// Fill up the contents of obj_porcess
//
// Copy objects from obj_porcess to objmap using a computed key.
for ( auto& item : obj_process )
{
objmap[std::string("process_") + item.first] = item.second;
}
Could you iterate over the map?
for(auto &i : obj_process)
objmap["process" + i.first] = i.second;

Using find_if with vector object

this code always returns false
I tried to pass lambda parameter by reference and I had the same result
any tip please
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(5);
for (int x : v1)
{
auto it = find_if(v1.begin(), v1.end(), [x](int y){ return x == y; });
if (it != v1.end())
return false;
return true;
}
To check for duplicates (not remove them, just check for them) then you can do something like this:
Get the first value, and check for it in the rest of the container. You should not check the first element again because that's the element we are checking currently.
If a duplicate is not found then go on to the second element, and check from the third element forward. WE don't need to check the first element because that was done in the previous step.
Then continue like that for all elements.
If you find a duplicate then stop the searching and return true. If none are found then continue until the end, and then return false.
This can be done easily using iterators:
// Outer loop, current element to check
for (auto const i = v1.begin(); i != v1.end(); ++i)
{
// Inner loop, the element to check against
for (auto const j = i + 1; j != v1.end(); ++j)
{
if (*i == *j)
return true; // Duplicate found
}
}
// No duplicates found
return false;
The above code shows the principle, you could of course use std::find_if instead of the inner loop. The important thing is to start looking at the next element. All the previous have already been checked, and you should not compare the current value with itself.
Look at your condition in the if. What you meant it to do and what it actually does?
From using for it looks like you want it to go over all the container. Can you find a case where the body of the loop doesn't return immediately on the first iteration?

Difference between one pass (scan) and two pass(scan)

I had an Interview, a day before.
The Interviewer told me to , " Write a program to add a node at the end of a linked list ".
I had given him a solution. but he told me to implement it in one pass (one scan).
Can Anybody explain me, whats the meaning of one pass, and how to find the program written is in one pass or two pass?
Here is my code
public void atLast(int new_data)
{
Node new_node=new Node(new_data);
if(head==null)
{
head=new Node(new_data);
return;
}
new_node.next=null;
Node last=head;
while(last.next!=null)
{
last=last.next;
}
last.next=new_node;
return;
}
If that is the code you gave the interviewer must have misread it because it is a single pass.
In your case a "pass" would be your while loop. It could also be done with recursion, for, or any other type of loop that goes through the elements in the array (or other form of a list of items).
In your code you run through the list of Node and insert the element at the end. This is done in one loop making it a single pass.
Now to look at a case with two passes. Say for example you were asked to remove the element with the largest value and wrote something similar to this:
int index = 0;
int count = 0;
int max = 0;
while(temp_node != null)
{
if(temp_node.data > max)
{
index = count;
max = temp_node.data;
}
count++;
temp_node = temp_node.next;
}
for(int i = 0; i < count; i++)
{
if(i == index)
{
//Functionality to remove node.
}
}
The first pass (while) detects the Node which has the maximum value. The second pass (for) removes this Node by looping through all the elements again until the correct one is found.
I'd imagine "two passes" here means that you iterated through the whole list twice in your code. You shouldn't need to do that to add a new node.

How to eliminate duplicate filename in hadoop mapreduce?

I want to eliminate duplicate filenames in my output of the hadoop mapreduce inverted index program. For example, the output is like - things : doc1,doc1,doc1,doc2 but I want it to be like
things : doc1,doc2
Well you want to remove duplicates which were mapped, i.e. you want to reduce the intermediate value list to an output list with no duplicates. My best bet would be to simply convert the Iterator<Text> in the reduce() method to a java Set and iterate over it changing:
while (values.hasNext()) {
if (!first)
toReturn.append(", ") ;
first = false;
toReturn.append(values.next().toString());
}
To something like:
Set<Text> valueSet = new HashSet<Text>();
while (values.hasNext()) {
valueSet.add(values.next());
}
for(Text value : valueSet) {
if(!first) {
toReturn.append(", ");
}
first = false;
toReturn.append(value.toString());
}
Unfortunately I do not know of any better (more concise) way of converting an Iterator to a Set.
This should have a smaller time complexity than orange's solution but a higher memory consumption.
#Edit: a bit shorter:
Set<Text> valueSet = new HashSet<Text>();
while (values.hasNext()) {
Text next = values.next();
if(!valueSet.contains(next)) {
if(!first) {
toReturn.append(", ");
}
first = false;
toReturn.append(value.toString());
valueSet.add(next);
}
}
Contains should be (just like add) constant time so it should be O(n) now.
To do this with the minimal amount of code change, just add an if-statement that checks to see if the thing you are about to append is already in toReturn:
if (!first)
toReturn.append(", ") ;
first = false;
toReturn.append(values.next().toString());
gets changed to
String v = values.next().toString()
if (toReturn.indexOf(v) == -1) { // indexOf returns -1 if it is not there
if (!first) {
toReturn.append(", ") ;
}
toReturn.append(v);
first = false
}
The above solution is a bit slow because it has to traverse the entire string every time to see if that string is there. Likely the best way to do this is to use a HashSet to collect the items, then combining the values in the HashSet into a final output string.

Resources