Цикл над структурой вектора <string> в C ++

0

Вопрос: Есть ли лучший способ перебрать все векторы в структуре, чем вызывать их один за другим, как показано в примере? #

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

3 ответа

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
    Мне нравится вектор векторов. Объедините это с enum {CARS, FOOD}, и теперь я могу получить доступ к векторам с членами [CARS]. Я уверен, как Python, где я могу перебирать такие вещи, как enum.
1

Попробуйте использовать 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;
}
  • 0
    Очень хорошее решение. Благодарю. Есть ли недостатки в использовании set и map over vector?
  • 0
    С помощью наборов и карт вы можете найти значение за O (ln n), а не за время O (n) с вектором. Что касается недостатков, то здесь нет упорядочивания элементов в большинстве наборов и типов карт, и вы будете использовать ничтожно больший объем памяти для каждого элемента.
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);
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню