Вопрос: Есть ли лучший способ перебрать все векторы в структуре, чем вызывать их один за другим, как показано в примере? #
Я создаю классификатор. Существует несколько категорий элементов, каждый из которых представлен вектором строки. Каждый из векторов будет довольно малым, <100 элементов. Я прочитал примеры в следующей ссылке:
Как найти, присутствует ли элемент в 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;
}
Вы можете сохранить структуру и сохранить указатели на каждый элемент структуры в списке или векторе.
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
}
Попробуйте использовать std :: map
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;
}
Я думаю, что 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);
}
int FindValue(vector<string>& vec, string keyWord)
наint FindValue(vector<string>& vec, const string& keyWord)
, вы копируете строку каждый раз, когда вызываетеFindValue
. Другое возможное улучшение - сортировка массива категорий и поиск с помощьюlower_bound
.