2014-09-05 47 views
0

问题:有没有更好的方法来循环遍历结构中的所有向量,而不是像在示例中所示的那样逐一调用它们? #在C++中向量<string>的循环遍历C++

我正在建立一个分类器。有几个类别的项目分别由一个字符串向量表示。每个矢量都相当小,100个元素。我在下面的链接阅读的例子:

How to find if an item is present in a std::vector?

下面是我实现的代码的简化例子。代码编译并运行,但对我来说似乎笨重。提前致谢。

#include "stdafx.h" 
#include <vector> 
#include <string> 
#include <iostream> 

using namespace std; 

struct Categories 
{ 
    vector <string> cars; 
    vector <string> food; 
}; 

struct ThingsType 
{ 
    Categories iLike; 
    Categories dontLike; 
}; 

typedef vector<string>::const_iterator vIter; 

int FindValue(vector<string>& vec, string keyWord) 
{ 
    int indx = -1; 
    vIter iter = find(vec.begin(), vec.end(), keyWord); 
    if (iter != vec.end()){ 
     // found it 
     std::cout << "Value: " << *iter << " found in location: " << iter - vec.begin() << endl; 
     indx = iter - vec.begin(); 
    } 
    else 
    { 
     // did not find it. 
     std::cout << "Value: " << keyWord << " not found." << endl; 
    } 
    return indx; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    int result[10]; 
    ThingsType things; 
    things.iLike.cars = { "Mustang", "Pinto" }; 
    things.dontLike.food = { "Squash" }; 
    string item("Pinto"); 
    // I want to loop over all vectors searching for items 
    result[0] = FindValue(things.iLike.cars, item); 
    result[1] = FindValue(things.iLike.food, item); 
    // . . . 
    result[9] = FindValue(things.dontLike.food, item); 

    return 0; 
} 
+3

变化:'INT FindValue(矢量&更多,串关键字)'的'INT FindValue(矢量&更多,常量字符串和关键字)',你每次调用'FindValue'时间复制的字符串。其他可能的改进是对类别数组进行排序并使用'lower_bound'查找。 – NetVipeC 2014-09-05 18:51:55

回答

1

您可以保留结构,并将指向每个结构成员的指针保存在一个列表或向量中。

struct Categories 
{ 
    vector <string> cars; 
    vector <string> food; 
}; 

std::vector<std::vector<string>*> members; 
Categories cat; 
members.push_back(&cat.cars); // add a pointer to the cars struct member 
members.push_back(&cat.food); // add a pointer to the food struct member 

现在你可以迭代通过成员,或通过结构访问。

for(std::vector<string>* member: members) 
{ 
    for(string s: *member) 
    { 

    } 
} 

或者你可以放弃的结构完全和使用向量的向量,这样你可以遍历的“成员”,同时仍然允许每个成员O(1)访问时间。

const int CARS = 0; 
const int FOOD = 1; 
members[CARS].push_back(car); // add a car 
members[FOOD].push_back(food); // add food 

// iterate cars 
for(string car: members[CARS]) 
{ 
    // do something 
} 
+0

我喜欢矢量的矢量。将它与枚举{CARS,FOOD}结合起来,现在我可以使用成员[CARS]访问向量。我确定喜欢python,我可以迭代诸如枚举之类的东西。 – user3784804 2014-09-05 19:11:14

1

尝试使用一个std ::地图

using namespace std; 

typedef set<string> CategoryType; 

struct ThingsType 
{ 
    map<string, CategoryType> iLike; 
    map<string, CategoryType> dontLike; 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    ThingsType things; 
    things.iLike['cars'].insert("Mustang"); 
    things.iLike['cars'].insert("Pinto"); 
    things.iLike['food'].insert("Squash"); 

    string item("Pinto"); 
    // I want to loop over all vectors searching for items 
    for(map<string, CategoryType>::const_iterator i = things.iLike.begin(); i != things.iLike.end(); i++) { 
     if (i->second.find(item) != set::end) 
      cout << "I like " << item << endl; 
    } 

    for(map<string, CategoryType>::const_iterator i = things.dontLike.begin(); i != things.dontLike.end(); i++) { 
     if (i->second.find(item) != set::end) 
      cout << "I don't like " << item << endl; 
    } 

    return 0; 
} 
+0

非常好的解决方案。谢谢。在矢量上使用set和map有什么缺点吗? – user3784804 2014-09-05 19:12:56

+0

使用集合和映射,您可以在O(ln n)时间中找到一个值,而不是使用矢量的O(n)时间。就劣势而言,大多数设置和地图类型中没有项目的排序,并且您将为每个项目使用的可用内存量可以忽略不计。 – 2014-10-05 21:11:03

0

我觉得std::unordered_set会在这种情况下更好。

#include<unordered_set> 

struct Categories{ 
    std::unordered_set <std::string> cars; 
    std::unordered_set <std::string> food; 
}; 

struct ThingsType{ 
    Categories iLike; 
    Categories dontLike; 
}; 

int main(){ 
    std::unordered_set<std::string>::iterator result[10]; 
    ThingsType things; 
    things.iLike.cars = { "Mustang", "Pinto" }; 
    things.dontLike.food = { "Squash" }; 
    string item("Pinto"); 
    result[0] = things.iLike.cars(item); 
    result[1] = things.iLike.food(item); 
    // . . . 
    result[9] = things.dontLike.food(item); 
}