views:

73

answers:

2

I have a std::map<int,int> lets call it my_map

I iterate through this map using iterators and a for loop.

Within each iteration I want to modify many elements in this map but restore it again to its original values for next iteration of the loop.

I thought I could create a temporary copy of the iterator my_temp_map , but then I wouldn't be able to use the iterator to find the element I ought to be working on.

I then thought I could create a temporary copy, work on the origin my_map and at the end of each loop restore the original back to the temporary copy. However I believe this would invalidate the iterators as an assignment deletes all elements

How does one solve this problem?

Code added

So each inner loop will modify current_partition (and there is some more absent code that will store the result of the modified current_partition), but after each inner_loop I need current_loop to be restored to its former self.

std::map<int,int> current_partition = bitset_to_map(centre->second->bit_partitions);
int num_parts = (std::max_element(current_partition.begin(), current_partition.end(),value_comparer))->second;

for (std::map<int,int>::iterator itr = current_partition.begin(); itr != current_partition.end(); ++itr) {
    for (int next_part = 0; next_part<num_parts+1; ++next_part) {
        if (next_part != itr->second) {
            int current_part = itr->second;
            itr->second = next_part;

            std::vector<int> first_changed_part, last_changed_part;
            for (std::map<int,int>::iterator new_itr = current_partition.begin(); new_itr != current_partition.end(); ++new_itr) {
                if (new_itr->second == current_part)
                    first_changed_part.push_back(new_itr->first);
                if (new_itr->second == next_part)
                    last_changed_part.push_back(new_itr->first);
            }
        }
    }
}
+1  A: 

I think that std::advance may be of help. Create the temp, then advance begin() until you're where you are now (found out with std::distance)...then whatever it is you're trying to do.

Noah Roberts
Alternatively, if you don't need to change the items before the current iterator position, you can create the temp map which contains only the elements from the current position to the end (using the constructor which takes iterators as parameters).
TreDubZedd
A: 

With the code, I understand what you're going for now. I'd do it pretty much the first way you suggest: each time through the outer loop, make a temporary copy of the current_partition data structure, and then work on that, discarding it at the end.

You said that the problem with that would be that you couldn't use an iterator into the original map to find the element you ought to be working on. That's true; you can't do that directly. But it's a map. The element you're working on will have a key which will be the same in any copy of the data structure, so you can use that to create an iterator to the element that you ought to be working on in the copy.

For instance:

std::map<int,int> current_partition = bitset_to_map(centre->second->bit_partitions);
int num_parts = (std::max_element(current_partition.begin(), current_partition.end(),value_comparer))->second;

for (std::map<int,int>::iterator itr = current_partition.begin(); itr != current_partition.end(); ++itr) {

    // Make a temporary copy of the map. Iterators between the original and the copy aren't
    // interchangeable, but the keys are.

    std::map<int,int> tmp_current_partition = current_partition;

    // Use the iterator itr to get the key for the element you're working on (itr->first),
    // and then use that key to get an equivalent iterator into the temporary map using find()

    std::map<int,int>::iterator tmp_itr = tmp_current_partition.find(itr->first);

    // Then just replace current_partition with tmp_current_partition and
    // itr with tmp_itr in the remainder (hopefully I didn't miss any)

    for (int next_part = 0; next_part<num_parts+1; ++next_part) {
        if (next_part != tmp_itr->second) {
            int current_part = tmp_itr->second;
            tmp_itr->second = next_part;

            std::vector<int> first_changed_part, last_changed_part;
            for (std::map<int,int>::iterator new_itr = tmp_current_partition.begin(); new_itr != tmp_current_partition.end(); ++new_itr) {
                if (new_itr->second == current_part)
                    first_changed_part.push_back(new_itr->first);
                if (new_itr->second == next_part)
                    last_changed_part.push_back(new_itr->first);
            }
        }
    }
}
Tyler McHenry