Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. ATL / WTL / STL
  4. STL "for_each" algorithm.

STL "for_each" algorithm.

Scheduled Pinned Locked Moved ATL / WTL / STL
c++cssalgorithmsquestionannouncement
21 Posts 5 Posters 1 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Jorgen Sigvardsson

    Well, but it is possible to alter the value.. :confused: That's why you get a reference to the container<T>::value_type instead of an iterator. In the map case, the value_type is a pair consisting of the key and value. -- You copy and paste yourself into my brain. You always find your way back into my brain.

    W Offline
    W Offline
    WREY
    wrote on last edited by
    #7

    Thanks again for replying. That being the case, I see little value in using the "for_each" algorithm when dealing with maps (perhaps with ANY container, since all the user is relegated to, is a set of "read only" type activities). You certainly seem to have more freedom in doing anything with ANY container by simply using the C++ "for" statement. ;P to the STL "for_each" algorithm. William Fortes in fide et opere!

    J 1 Reply Last reply
    0
    • W WREY

      Thanks again for replying. That being the case, I see little value in using the "for_each" algorithm when dealing with maps (perhaps with ANY container, since all the user is relegated to, is a set of "read only" type activities). You certainly seem to have more freedom in doing anything with ANY container by simply using the C++ "for" statement. ;P to the STL "for_each" algorithm. William Fortes in fide et opere!

      J Offline
      J Offline
      Jorgen Sigvardsson
      wrote on last edited by
      #8

      What are you talking about? As Michael Dunn pointed out, you get a pair<const string,string>& as an argument to your functor. If you want to modify the value, just do arg.second = whatever_you_fancy. for_each does not relegate the user to read only types.

      struct addone {
      void operator()(std::map<int, int>::value_type & arg) const {
      arg.second++;
      }
      };

      What is so read only with that? You cannot modify the key at all since it may break the ordering restrictions of the associative container - this by design so that these containers can be implemented using hash tables or search trees. You cannot modify the container itself because it could invalidate iterators for the algorithms in ways that cannot be anticipated. What you must have is an extra level of indirection because of the associativity rules - in this case the container itself. Since you are modifying order (keys) - not values - you need to handroll your own algorithm. -- You copy and paste yourself into my brain. You always find your way back into my brain.

      W 1 Reply Last reply
      0
      • J Jorgen Sigvardsson

        What are you talking about? As Michael Dunn pointed out, you get a pair<const string,string>& as an argument to your functor. If you want to modify the value, just do arg.second = whatever_you_fancy. for_each does not relegate the user to read only types.

        struct addone {
        void operator()(std::map<int, int>::value_type & arg) const {
        arg.second++;
        }
        };

        What is so read only with that? You cannot modify the key at all since it may break the ordering restrictions of the associative container - this by design so that these containers can be implemented using hash tables or search trees. You cannot modify the container itself because it could invalidate iterators for the algorithms in ways that cannot be anticipated. What you must have is an extra level of indirection because of the associativity rules - in this case the container itself. Since you are modifying order (keys) - not values - you need to handroll your own algorithm. -- You copy and paste yourself into my brain. You always find your way back into my brain.

        W Offline
        W Offline
        WREY
        wrote on last edited by
        #9

        Thanks for replying. Prior to my response, I had done this.

        void FnObj::operator() (const PAIR_KV& PA)
        {
        PAIR_KV PAIR = PA;

        if(PAIR.first == "Old Key")     // essentially doing the 'find'
        {
            PAIR.second = "This is the NEW value for the old key";
        }
        

        }

        As you can see, I typed in a new string value to the old key second argument. When I ran the program and displayed its content, the new string value did not get shown. The old value was still in the map. Unless I am absolutely not supposed to do ANYTHING inside the function object routine, this is what I'm talking about. William Fortes in fide et opere!

        J 1 Reply Last reply
        0
        • W WREY

          Thanks for replying. Prior to my response, I had done this.

          void FnObj::operator() (const PAIR_KV& PA)
          {
          PAIR_KV PAIR = PA;

          if(PAIR.first == "Old Key")     // essentially doing the 'find'
          {
              PAIR.second = "This is the NEW value for the old key";
          }
          

          }

          As you can see, I typed in a new string value to the old key second argument. When I ran the program and displayed its content, the new string value did not get shown. The old value was still in the map. Unless I am absolutely not supposed to do ANYTHING inside the function object routine, this is what I'm talking about. William Fortes in fide et opere!

          J Offline
          J Offline
          Jorgen Sigvardsson
          wrote on last edited by
          #10

          Of course nothing happened with the old values in your map. Look at what you're doing! You're accepting a PAIR_KV by const reference. You then assign it to a stack based PAIR_KV object. You get a copy! You are modifying the local copy on the stack. Do this instead

          typedef map<string, string> MapStr;

          void FnObj::operator() (MapStr::value_type& PA) {
          if(PA.first == "Old Key") {
          PA.second = "This is the NEW value for the old key";
          }
          }

          Why did you have a const string as key to begin with? Look, I seriously believe that you should get a good book on STL. I recommend Generic Programming and the STL: Using and Extending the C++ Standard Template Library by Matthew H. Austern, ISBN 0201309564. -- You copy and paste yourself into my brain. You always find your way back into my brain.

          W 1 Reply Last reply
          0
          • J Jorgen Sigvardsson

            Of course nothing happened with the old values in your map. Look at what you're doing! You're accepting a PAIR_KV by const reference. You then assign it to a stack based PAIR_KV object. You get a copy! You are modifying the local copy on the stack. Do this instead

            typedef map<string, string> MapStr;

            void FnObj::operator() (MapStr::value_type& PA) {
            if(PA.first == "Old Key") {
            PA.second = "This is the NEW value for the old key";
            }
            }

            Why did you have a const string as key to begin with? Look, I seriously believe that you should get a good book on STL. I recommend Generic Programming and the STL: Using and Extending the C++ Standard Template Library by Matthew H. Austern, ISBN 0201309564. -- You copy and paste yourself into my brain. You always find your way back into my brain.

            W Offline
            W Offline
            WREY
            wrote on last edited by
            #11

            You are great on the giving of advice, but very poor on the testing of your own advice, because if you had tested the advice you were giving, you would have discovered they DON'T WORK. I know they don't work because I applied what you suggested and ended up (the latest) with 6 errors!! Moreover, if you had looked closely, you would have seen that I had:

            typedef pair<string, string> PAIR_KV;

            That's my "value_type" for the map that you keep talking about so much. It's there! SEE! It's there! I don't need your "MapStr::value_type&" suggestion, but I used it anyway just to see if it would work, ... and IT DIDN'T!! So much for your well-informed advice. Yes, I had tried removing "const" from all the places they were being used and ended up with errors of one kind or another, and even tried using the reference straight from the parameter list of the function object "operator()" (without creating one on the stack). That didn't work either (meaning, it produced several errors)! If you had done the various testings as I did, you would have found that "for_each" is just not a good algorithm for dealing with maps. It's obvious you didn't know that, based on the incorrect advice you have been giving. NONE of the advice you have given so far worked. NONE! But there you are, telling me to go read up on certain STL books. FYI, I do my share of reading, and practicing with the STL almost every day. I certainly DON'T NEED another one of your gratuitous advice. KISS OFF!! William Fortes in fide et opere!

            J 1 Reply Last reply
            0
            • W WREY

              You are great on the giving of advice, but very poor on the testing of your own advice, because if you had tested the advice you were giving, you would have discovered they DON'T WORK. I know they don't work because I applied what you suggested and ended up (the latest) with 6 errors!! Moreover, if you had looked closely, you would have seen that I had:

              typedef pair<string, string> PAIR_KV;

              That's my "value_type" for the map that you keep talking about so much. It's there! SEE! It's there! I don't need your "MapStr::value_type&" suggestion, but I used it anyway just to see if it would work, ... and IT DIDN'T!! So much for your well-informed advice. Yes, I had tried removing "const" from all the places they were being used and ended up with errors of one kind or another, and even tried using the reference straight from the parameter list of the function object "operator()" (without creating one on the stack). That didn't work either (meaning, it produced several errors)! If you had done the various testings as I did, you would have found that "for_each" is just not a good algorithm for dealing with maps. It's obvious you didn't know that, based on the incorrect advice you have been giving. NONE of the advice you have given so far worked. NONE! But there you are, telling me to go read up on certain STL books. FYI, I do my share of reading, and practicing with the STL almost every day. I certainly DON'T NEED another one of your gratuitous advice. KISS OFF!! William Fortes in fide et opere!

              J Offline
              J Offline
              Jorgen Sigvardsson
              wrote on last edited by
              #12

              #include <map>
              #include <iostream>
              #include <utility>
              #include <algorithm>

              typedef std::map<int, int> IntMap;

              struct addone {
              void operator()(IntMap::value_type& v) const {
              v.second++;
              }
              };

              struct print {
              void operator()(IntMap::value_type& v) const {
              std::cout << "first = " << v.first << ", second = " << v.second << std::endl;
              }
              };

              int main(int argc, char* argv[])
              {
              IntMap map;

              map.insert(std::make\_pair(1, 1));
              map.insert(std::make\_pair(2, 2));
              map.insert(std::make\_pair(3, 3));
              map.insert(std::make\_pair(4, 4));
              map.insert(std::make\_pair(5, 5));
              
              std::for\_each(map.begin(), map.end(), print());
              std::for\_each(map.begin(), map.end(), addone());
              std::for\_each(map.begin(), map.end(), print());
              
              return 0;
              

              }

              I'm just being honest; Do yourself a favor - stop whining and pick up an STL book. -- You copy and paste yourself into my brain. You always find your way back into my brain.

              W 1 Reply Last reply
              0
              • J Jorgen Sigvardsson

                #include <map>
                #include <iostream>
                #include <utility>
                #include <algorithm>

                typedef std::map<int, int> IntMap;

                struct addone {
                void operator()(IntMap::value_type& v) const {
                v.second++;
                }
                };

                struct print {
                void operator()(IntMap::value_type& v) const {
                std::cout << "first = " << v.first << ", second = " << v.second << std::endl;
                }
                };

                int main(int argc, char* argv[])
                {
                IntMap map;

                map.insert(std::make\_pair(1, 1));
                map.insert(std::make\_pair(2, 2));
                map.insert(std::make\_pair(3, 3));
                map.insert(std::make\_pair(4, 4));
                map.insert(std::make\_pair(5, 5));
                
                std::for\_each(map.begin(), map.end(), print());
                std::for\_each(map.begin(), map.end(), addone());
                std::for\_each(map.begin(), map.end(), print());
                
                return 0;
                

                }

                I'm just being honest; Do yourself a favor - stop whining and pick up an STL book. -- You copy and paste yourself into my brain. You always find your way back into my brain.

                W Offline
                W Offline
                WREY
                wrote on last edited by
                #13

                KISS OFF!! Who needs your crappy little "int" addone sample? I've had enough of your unworkable samples in the past. I don't need anymore. If you didn't understand my last message, it states, "I do my share of reading just about everyday." I DON'T NEED you to tell me what to do. Take your crappy little "map.insert" sample and SHOVE IT!! It wouldn't hurt for you to do some reading of your own also. You clearly need it. All those unworkable advice you've been giving. You definitely need to do a lot of reading yourself. William Fortes in fide et opere!

                J J 2 Replies Last reply
                0
                • W WREY

                  KISS OFF!! Who needs your crappy little "int" addone sample? I've had enough of your unworkable samples in the past. I don't need anymore. If you didn't understand my last message, it states, "I do my share of reading just about everyday." I DON'T NEED you to tell me what to do. Take your crappy little "map.insert" sample and SHOVE IT!! It wouldn't hurt for you to do some reading of your own also. You clearly need it. All those unworkable advice you've been giving. You definitely need to do a lot of reading yourself. William Fortes in fide et opere!

                  J Offline
                  J Offline
                  Jorgen Sigvardsson
                  wrote on last edited by
                  #14

                  At least you're entertaining. :) -- You copy and paste yourself into my brain. You always find your way back into my brain.

                  W S 2 Replies Last reply
                  0
                  • J Jorgen Sigvardsson

                    At least you're entertaining. :) -- You copy and paste yourself into my brain. You always find your way back into my brain.

                    W Offline
                    W Offline
                    WREY
                    wrote on last edited by
                    #15

                    Even that you lack. William Fortes in fide et opere!

                    1 Reply Last reply
                    0
                    • W WREY

                      KISS OFF!! Who needs your crappy little "int" addone sample? I've had enough of your unworkable samples in the past. I don't need anymore. If you didn't understand my last message, it states, "I do my share of reading just about everyday." I DON'T NEED you to tell me what to do. Take your crappy little "map.insert" sample and SHOVE IT!! It wouldn't hurt for you to do some reading of your own also. You clearly need it. All those unworkable advice you've been giving. You definitely need to do a lot of reading yourself. William Fortes in fide et opere!

                      J Offline
                      J Offline
                      jbarton
                      wrote on last edited by
                      #16

                      The code example provided by Jörgen Sigvardsson was correctly updating a map of ints. It is easy to change this example to work with strings. #include <map> #include <iostream> #include <utility> #include <algorithm> #include <string> typedef std::map<std::string,std::string> StringMap; struct update { void operator() ( StringMap::value_type& v ) const { if ( v.first == "second" ) v.second = "replaced value"; } }; struct print { void operator() ( StringMap::value_type& v ) const { std::cout << "first = " << v.first << ", second = " << v.second << std::endl; } }; int main( int argc, char* argv[] ) { StringMap testMap; testMap.insert( StringMap::value_type("first", "1") ); testMap.insert( StringMap::value_type("second", "2") ); testMap.insert( StringMap::value_type("third", "3") ); testMap.insert( StringMap::value_type("fourth", "4") ); testMap.insert( StringMap::value_type("fifth", "5") ); std::for_each(testMap.begin(), testMap.end(), print()); std::for_each(testMap.begin(), testMap.end(), update()); std::for_each(testMap.begin(), testMap.end(), print()); return 0; } However, as you know (from your comments in your original post), the code in the "update" functor is basically doing a find. However, since the for_each does a loop through all elements of the map, this is much less efficient than doing an actual find. If you need to do single updates to elements in a map which have particular key values, it would normally be better to just do the find and then update the element. The for_each algorithm is really only appropriate if you need to access every element in the container. Best regards, John

                      W J 2 Replies Last reply
                      0
                      • J jbarton

                        The code example provided by Jörgen Sigvardsson was correctly updating a map of ints. It is easy to change this example to work with strings. #include <map> #include <iostream> #include <utility> #include <algorithm> #include <string> typedef std::map<std::string,std::string> StringMap; struct update { void operator() ( StringMap::value_type& v ) const { if ( v.first == "second" ) v.second = "replaced value"; } }; struct print { void operator() ( StringMap::value_type& v ) const { std::cout << "first = " << v.first << ", second = " << v.second << std::endl; } }; int main( int argc, char* argv[] ) { StringMap testMap; testMap.insert( StringMap::value_type("first", "1") ); testMap.insert( StringMap::value_type("second", "2") ); testMap.insert( StringMap::value_type("third", "3") ); testMap.insert( StringMap::value_type("fourth", "4") ); testMap.insert( StringMap::value_type("fifth", "5") ); std::for_each(testMap.begin(), testMap.end(), print()); std::for_each(testMap.begin(), testMap.end(), update()); std::for_each(testMap.begin(), testMap.end(), print()); return 0; } However, as you know (from your comments in your original post), the code in the "update" functor is basically doing a find. However, since the for_each does a loop through all elements of the map, this is much less efficient than doing an actual find. If you need to do single updates to elements in a map which have particular key values, it would normally be better to just do the find and then update the element. The for_each algorithm is really only appropriate if you need to access every element in the container. Best regards, John

                        W Offline
                        W Offline
                        WREY
                        wrote on last edited by
                        #17

                        Thanks for replying. Your sample does work. :-D William Fortes in fide et opere!

                        1 Reply Last reply
                        0
                        • J jbarton

                          The code example provided by Jörgen Sigvardsson was correctly updating a map of ints. It is easy to change this example to work with strings. #include <map> #include <iostream> #include <utility> #include <algorithm> #include <string> typedef std::map<std::string,std::string> StringMap; struct update { void operator() ( StringMap::value_type& v ) const { if ( v.first == "second" ) v.second = "replaced value"; } }; struct print { void operator() ( StringMap::value_type& v ) const { std::cout << "first = " << v.first << ", second = " << v.second << std::endl; } }; int main( int argc, char* argv[] ) { StringMap testMap; testMap.insert( StringMap::value_type("first", "1") ); testMap.insert( StringMap::value_type("second", "2") ); testMap.insert( StringMap::value_type("third", "3") ); testMap.insert( StringMap::value_type("fourth", "4") ); testMap.insert( StringMap::value_type("fifth", "5") ); std::for_each(testMap.begin(), testMap.end(), print()); std::for_each(testMap.begin(), testMap.end(), update()); std::for_each(testMap.begin(), testMap.end(), print()); return 0; } However, as you know (from your comments in your original post), the code in the "update" functor is basically doing a find. However, since the for_each does a loop through all elements of the map, this is much less efficient than doing an actual find. If you need to do single updates to elements in a map which have particular key values, it would normally be better to just do the find and then update the element. The for_each algorithm is really only appropriate if you need to access every element in the container. Best regards, John

                          J Offline
                          J Offline
                          Jorgen Sigvardsson
                          wrote on last edited by
                          #18

                          jbarton wrote: If you need to do single updates to elements in a map which have particular key values, it would normally be better to just do the find and then update the element. That depends a little on how many values you are updating. If you are updating few elements, then the approach you mention is more efficient. But if the number of values are many, then an iteration is faster. Assuming that the map is implemented as a balanced search tree, you need to find out how O(k * log(n)) relates to O(n), where k is the number of values to update, and n is the number of elements in the map. Of course, if it's a hashmap, then the approach you mention is most likely faster for basically all k (unless, of course, the hash algorithm is very slow). I guess it would be advantageous to encapsulate this algorithm into its own function, and let itself adapt to the problem size automatically. But hey, how would I know? I just post faulty samples and is a retard according to some. :) -- You're entertaining at least.

                          J 1 Reply Last reply
                          0
                          • J Jorgen Sigvardsson

                            jbarton wrote: If you need to do single updates to elements in a map which have particular key values, it would normally be better to just do the find and then update the element. That depends a little on how many values you are updating. If you are updating few elements, then the approach you mention is more efficient. But if the number of values are many, then an iteration is faster. Assuming that the map is implemented as a balanced search tree, you need to find out how O(k * log(n)) relates to O(n), where k is the number of values to update, and n is the number of elements in the map. Of course, if it's a hashmap, then the approach you mention is most likely faster for basically all k (unless, of course, the hash algorithm is very slow). I guess it would be advantageous to encapsulate this algorithm into its own function, and let itself adapt to the problem size automatically. But hey, how would I know? I just post faulty samples and is a retard according to some. :) -- You're entertaining at least.

                            J Offline
                            J Offline
                            jbarton
                            wrote on last edited by
                            #19

                            I think the idea of iterating through the map to update multiple elements has merit. If (for instance) I want to update the data associated with all keys that match a particular pattern, there really isn't any way that I could do it without iterating through all elements in the map. When I have a list of specific key values whose data I want to update, I find it difficult to set up a functor that efficiently checks for these key values and then updates the associated data values. It may be possible using another map or hash within the functor to lookup the key value and then get the replacement value. With only simple if / else if comparisons, I think that the overhead of the functor would probably remove any advantage gained by not using find on each key value. Unless the program I was writing was running too slowly and by profiling I found it to be due to using find to update the map, I would probably stick with using find. If you know of a better way of writing this functor, let me know. I am always interested in hearing other approaches. Best regards, John

                            1 Reply Last reply
                            0
                            • J Jorgen Sigvardsson

                              At least you're entertaining. :) -- You copy and paste yourself into my brain. You always find your way back into my brain.

                              S Offline
                              S Offline
                              Sebastian Benitez
                              wrote on last edited by
                              #20

                              Oh, please guys, continue fighting. This is very funny :laugh: "semper aliquid haeret", Bacon. -- Sebastián.

                              J 1 Reply Last reply
                              0
                              • S Sebastian Benitez

                                Oh, please guys, continue fighting. This is very funny :laugh: "semper aliquid haeret", Bacon. -- Sebastián.

                                J Offline
                                J Offline
                                Jorgen Sigvardsson
                                wrote on last edited by
                                #21

                                Hey, I'm not fighting. :) -- You're entertaining at least.

                                1 Reply Last reply
                                0
                                Reply
                                • Reply as topic
                                Log in to reply
                                • Oldest to Newest
                                • Newest to Oldest
                                • Most Votes


                                • Login

                                • Don't have an account? Register

                                • Login or register to search.
                                • First post
                                  Last post
                                0
                                • Categories
                                • Recent
                                • Tags
                                • Popular
                                • World
                                • Users
                                • Groups