2015-07-13 22 views
0

例如,我已經定義了類Foo和向量VEC:在C++中,如何通過給對象的成員找到對象向量中的某些項目?

#include <iostream> 
#include <vector> 
#include <algorithm> 
using namespace std; 
class foo { 
public: 
    foo(int flag, char ch):flag(flag), ch(ch) {} 
    int flag; 
    char ch; 
}; 
int main(void) 
{ 
    vector<foo> vec; 
    vec.push_back(foo(1,'a')); 
    vec.push_back(foo(2,'b')); 
    vec.push_back(foo(3,'c')); 
    //blabla... 
} 

我發現如何找到一個元素:How to find an item in a std::vector?
但現在我想只給一個char找對象,比如'b'。我怎樣纔能有效地實現這個目標?

+0

你知道如何遍歷一個向量並使用==運算符嗎? –

+0

你也可以使用'std :: find'。 –

+0

@DavidHaim我知道,但是我覺得當矢量變得太大時效率很低。所以...^_^ –

回答

6

您可以使用std::find_if此:

//c++14 
std::find_if(std::begin(vec),std::end(vec), 
       [](auto&& v) { return v.ch == 'b'; }) 

//c++11 
std::find_if(std::begin(vec),std::end(vec), 
       [](const foo& v) { return v.ch == 'b'; }) 

你可以在一個功能包裝這件事,如果你發現自己需要這種格局多次:

//c++14, c++11 version left as exercise 
decltype(auto) find_foo (const std::vector<foo>& vec, char c) 
{ 
    return std::find_if(std::begin(vec),std::end(vec), 
         [c](auto&& v) { return v.ch == c; }); 
} 

一個更好的選擇可能是使用std::unordered_map<char,int>代替std::vector<foo>

int main() 
{ 
    std::unordered_map<char,int> my_map; 
    my_map['a'] = 1; 
    my_map['b'] = 2; 
    my_map['c'] = 3; 

    cout << my_map['b']; //instead of that std::find_if nonsense 
} 
+0

Em ...謝謝你的回答,但我的編譯器說,你的第一個代碼塊中的'auto'是不允許的,我不會不知道爲什麼。我正在使用Visul Studio 2012. –

+0

這是一個C++ 14功能,只需使用'const foo&'來代替。 – TartanLlama

+0

好的。非常感謝。 –

0

如果矢量排序(如您的示例),則可以使用lower_bound來獲得對數性能。如果矢量未排序,則可以使用查找來獲得線性性能。

2

您可以使用在標頭<algorithm>中聲明的標準算法std::find_if。例如

#include <iostream> 
#include <algorithm> 

class foo { 
public: 
    foo(int flag, char ch):flag(flag), ch(ch) {} 
    int flag; 
    char ch; 
}; 

int main() 
{ 
    std::vector<foo> vec; 

    vec.push_back(foo(1,'a')); 
    vec.push_back(foo(2,'b')); 
    vec.push_back(foo(3,'c')); 

    char ch = 'b'; 
    auto it = std::find_if(vec.begin(), vec.end(), 
          [&](const foo &f) { return f.ch == ch; }); 

    if (it != vec.end()) std::cout << it->flag << ' ' << it->ch << std::endl; 

}  

如果編譯器支持C++ 14然後lambda表達式也可以寫成下面的方式

auto it = std::find_if(vec.begin(), vec.end(), 
         [ch = 'b'](const foo &f) { return f.ch == ch; }); 

另一種方法是使SEACH作爲類本身的界面。例如

class foo { 
public: 
    foo(int flag, char ch):flag(flag), ch(ch) {} 
    int flag; 
    char ch; 
    class find_by_ch 
    { 
    public:   
     find_by_ch(char ch) : ch(ch) {} 
     bool operator()(const foo &f) const { return f.ch == ch; } 
    private: 
     char ch; 
    };   
}; 

//... 

auto it = std::find_if(vec.begin(), vec.end(), foo::find_by_ch('b')); 
+0

@Harold Huang什麼不清楚?另見我更新的帖子。:) –

+0

哦,我已經說清楚了。太感謝了!後一種方法是鼓舞人心的。 –

+0

但似乎接受多個答案是不允許的,對不起。 –

1

定義僅使用char作爲參數用於foo一個隱式的構造。

foo(char ch) : ch(ch), flag(int()) { 
} 

OR添加默認的參數傳遞給您現有的構造

foo(char ch, int flag = int()) : ch(ch), flag(flag) { 
} 

重載比較運算符

bool operator ==(const char & rhs) { 
    return ch == rhs; 
} 

然後,您可以直接使用std::find

vector<foo>::iterator it = std::find(vec.begin(), vec.end(), 'b'); 
if (it != vec.end()) { 
    ... // do something 
} 

一個工作代碼就看起來像

#include <iostream> 
#include <vector> 
#include <algorithm> 
using namespace std; 

class foo { 
public: 
    foo(char ch, int flag = int()) : flag(flag), ch(ch) {} 
    int flag; 
    char ch; 
    inline bool operator ==(const char & rhs) { return ch == rhs; } 
}; 

int main(void) { 
    vector<foo> vec; 
    vec.push_back(('a', 1)); 
    vec.push_back(('b', 2)); 
    vec.push_back(('c', 3)); 
    vector<foo>::iterator it = find(vec.begin(), vec.end(), 'b'); 
    if (it != vec.end()) 
     cout << "found" << endl; 
    return 0; 
} 

http://ideone.com/ue907i演示。

+0

如果沒有重載的'operator ==',這將不起作用。 –

+0

@ BenjaminLindley你是對的。謝謝,修復。 – Shreevardhan

相關問題