2015-04-07 66 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。我會保持原樣。 –