简体   繁体   中英

Can stl functions that work on each member of a container accept external parameters?

I plan to execute an operation on each data of a std::vector array as the following codes show:

std::vector<int> abc;
abc.push_back(1);
abc.push_back(5);
abc.push_back(2);
std::sort(abc);
int min = abc[0];
int max = abc[2];
for(int i=0; i<3; i++)
  abc[i] = (abc[i]-min)/(max-min);

The question I have now is that whehter I have more elegant way of performing

 for(int i=0; i<3; i++)
      abc[i] = (abc[i]-min)/(max-min)

with for_each , trasnform or other methods in stl. The difficulty I have with these functions lies in the fact that I do not know how to incorporate external parameters within them.

Here is an example that uses for_each to update each element in abc :

std::for_each(abc.begin(),    // Start of range
              abc.end(),      // End of range
              [=](int &value) // The operation to apply
              {
                value=(value-min)/(max-min);
              });

Changing the sequence being iterated over by for_each is often frowned upon, despite the fact that for_each guarantees the order of traversal as well as how many invocations occur per element. However, to appease the naysayers, you may want to use transform instead which has no such guarantees (neither of the order of traversal nor of the number of calls of the predicate other than via a complexity guarantee {Note: the complexity has been modified to a guarantee of the number of calls in C++11, see 25.3.4.4}):

std::transform(abc.begin(),    // Start of source range
               abc.end(),      // End of source range
               abc.begin(),    // Start of destination range
               [=](int value)  // The operation to apply
               {
                 return (value-min)/(max-min);
               });

By the way, since you're doing integer division in your formula, you have to be very careful with the truncation of the result. You should probably check for a divide by zero, as well.

With C++11 you could use a lambda that captures the needed variables:

std::transform(std::begin(abc), std::end(abc),
               std::begin(abc),
               [=](int x) { return (x-min)/(max-min); });

This is equivalent to your loop, although you might want to verify whether the logic was correct in the first place.

This is easily achieved using std::transform and a suitable functor. Here, a lambda is used for brevity:

std::transform(std::begin(abc), 
               std::end(abc),
               std::begin(abc), 
               [&](int i) { return (i-min)/(max-min); }); 

It isn't clear whether this is an improvement. I would just write a plain range-based loop:

for(int& i : abc)
  i = (i-min)/(max-min);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM