2015-04-07 65 views
0

我很喜欢用C++ 11,并试图想出一个更优雅的方式来对两个std::vector<double>进行两两比较。对于成对最大,我使用的是相当不雅使用C++ 11 std :: vector元素进行两两比较lambda表达式

typedef std::vector<double> vec; 
vec pairwiseMax(vec& a, vec& b) 
{ 
    ASSERT(a.size() == b.size()); 
    vec c(a); // seed with a 
    for (unsigned int i = 0; i < a.size(); i++) 
    { 
     if (b[i] > a[i]) // bigger than 
      c[i] = b[i]; 
    } 
    return c; 
} 

但是,使用lambda表达式和std::for_each似乎更好,因为其中提取std::vector<double>的绝对最大下面,但我不来了什么。

inline double vecabs(vec v) 
{ 
    if (v.empty()) return 0.0; 
    vec::iterator it = 
     std::max_element(v.begin(), v.end(), 
     // Start lambda function 
     [](double const& a, double const& b) 
     { 
      return (std::abs(a) < std::abs(b)); 
     }); 
    return *it; 
}; 

伊戈尔的文章后,我现在有:

vec c; 
c.reserve(a.size()); 
std::transform(a.begin(), a.end(), b.begin(), 
    std::back_inserter(c), 
    [](double const& d, double const& e) 
    { return max(d, e); }); 

两个问题:

  1. 为什么不直接复制到vec avec c我以前?
  2. 是不是使用back_inserter添加了很多额外的操作?如果从c==a开始,那么将需要更少的插入到c

像这样:

vec c(a); // seed with a 
std::transform(a.begin(), a.end(), b.begin(), 
    c.begin(), 
    [](double const& d, double const& e) 
    { return max(d, e); }); 
return c; 
+0

伊戈尔的方法更高效那么你原来的方法。如果a和b包含均匀分布的随机值,那么您的原始方法将创建1.5 N个副本,但Igor的方法仅创建1 N个副本。 – atb

回答

3
vec c; 
c.reserve(a.size()); 
std::transform(a.begin(), a.end(), b.begin(), 
       std::back_inserter(c), 
       std::max<double>); 
+0

你可能想添加'c.reserve(a.size())' – druckermanly

+0

@igor - 没有找到'std :: transform' - 谢谢!你的建议不起作用,因为'std :: max '有多个重载(像这里:http://stackoverflow.com/questions/11626304/is-it-possible-to-use-stdaccumulate-with-stdmin) 。 – Colin

+0

如果我们使用匿名函数,可以使其工作。看到我的回应。 –

1

伊戈尔的解决方案是伟大的,但我遇到了麻烦编译它。我发现我需要在一个匿名函数中包装std :: max来让它编译。

这里是它们允许以成对的最大的矢量任意数量的两个模板功能:

// pairwise maximum            
template<typename T>            
vector<T> pmax(const std::vector<T>& a, const std::vector<T>& b) { 
    std::vector<T> c;            
    assert(a.size() == b.size());         
    c.reserve(a.size());           
    std::transform(a.begin(), a.end(), b.begin(),     
        std::back_inserter(c),       
        [](T a, T b) { return std::max<T>(a, b); }); 
    return c;              
}                 

// maximum of all vectors 
template<typename T>              
vector<T> vpmax(const std::vector<std::vector<T>>& vv) {     
    std::vector<T> c;              
    if (vv.empty()) return c;            
    c = vv.front();              
    typename std::vector<std::vector<T> >::const_iterator v = vv.begin(); 
    ++v; // skip the first element           
    for (; v != vv.end(); ++v) {           
     c = pmax(c, *v);             
    }                  
    return c;                
} 
+0

您可能已经有了一个最大定义(例如Visual Studio)。如果是这样,只需写入“(std :: max)”而不是“std :: max”,以使预处理器将其识别为单个实体。不需要额外的功能。 – Colin

+0

啊,有趣。我可以尝试一下。 –

+0

它似乎并不适用于gcc。我会保持原样。 –