Инициализировать пустой вектор векторов с элементами вектора векторов - PullRequest
0 голосов
/ 07 февраля 2020

У меня есть функция, которая инициализирует пустой вектор векторов из строки типа с определенными элементами из данного вектора векторов из строки типа. Мой синтаксис выглядит следующим образом

std::vector<std::vector<std::string>> extract_data_on_userid(const std::vector<std::vector<std::string>> &array, std::vector<std::string> &user_ids, const int nr_of_events)
{
  std::vector<std::vector<std::string>> data_extract;
  int event_iterator = 0;
  int user_id_iterator = 0;

  // While loops which extracts the events based on user IDs
  while (event_iterator <= nr_of_events)
  {
    // While loop which finds specified user id in an event
    while (user_id_iterator < array[0].size())
    {
      if (check_id(user_ids, array[0][user_id_iterator]))
      {
        for (size_t i = 0; i < array.size(); i++)
        {
          data_extract[i].push_back(array[i][user_id_iterator]);
        }
      }
      user_id_iterator++;
    }

    event_iterator++;
  }

  return data_extract;
}

Данный вектор состоит из различного числа строковых векторов (не менее 2). Мой метод должен искать определенные идентификаторы пользователя в

check_id(user_ids, array[0][user_id_iterator])

и затем pu sh соответствующее событие (user_id_iterator) в новом 2D векторе для всех 1D векторов

vector[i:in][user_id_iterator]

во вновь Инициированный вектор

std::vector<std::vector<std::string>> data_extract;

сверх для l oop.

 for (size_t i = 0; i < array.size(); i++)
    {
      data_extract[i].push_back(array[i][user_id_iterator]);
    }

Все работает, как и ожидалось, пока элементы векторов [i: in] в строке [user_id_iterator] должны быть вставлены в векторы emtpy.

Должен ли я изначально инициализировать все одномерные векторы в двумерном векторе data_extract? Каков правильный синтаксис для заполнения пустого вектора векторов, который определенных элементов из заполненного вектора векторов? Я получаю исключение (ошибка сегментации), потому что вектор emtpy не инициализирован правильно.

Ответы [ 2 ]

1 голос
/ 08 февраля 2020

Вы допустили простую ошибку, которую легко исправить.

Ваш двумерный вектор

std::vector<std::vector<std::string>> data_extract;

пуст после определения. Это означает, что он не содержит ни одного элемента, ни в каком измерении. Даже не элемент с индексом [0] или [0][0]. Итак, у вас есть ошибка, потому что вы обращались к элементу [i], который не существует.

Итак, да, как вы и предполагали, вы должны инициализировать вектор. Есть несколько возможностей. Вы можете установить начальный размер, используя конструктор std::vector, описанный здесь . Номер 3) или 4)

Так, например:

std::vector<std::vector<std::string>> data_extract(array.size());

Что, вероятно, является наиболее ценным решением.

Вы также можете resize свой вектор после определения

data_extract.resize(array.size());

но это дополнительная строка кода, которая не нужна, потому что вы можете сделать это в конструкторе. Конечно, вы также можете инициализировать оба измерения вашего вектора, если знаете размер второго измерения.

std::vector<std::vector<std::string>> data_extract(array.size(),std::vector<std::string>(array[0].size(),""));

Кстати. Твоя внешность, пока l oop не работает.

while (event_iterator <= nr_of_events)

"Event_iterator" нигде не используется в теле l oop, а внутренние циклы while никогда не запускаются. Это потому, что во 2-м раунде внешнего l oop, "user_id_iterator" уже biiger, чем "array [0] .size ()" и внутренний l oop никогда не запустится.

Также остальная часть логики c трудна для понимания. Я не уверен, почему вы всегда ссылаетесь на «массив [0]».

1 голос
/ 07 февраля 2020

Ваш дефект сегментации трудно найти, так как вы реализовали слишком сложную функцию. Есть несколько простых мер рефакторинга, которые уменьшают шум, который генерируется здесь:

Вызов вектора строковых векторов array действительно раздражает. Вместо этого попробуйте переименовать и создать псевдонимы (не зная точно вашего контекста):

using TUserIdEvents = std::vector<std::vector<std::string>>;

TUserIdEvents extract_data_on_userid(const TUserIdEvents &eventsOfUserIds, std::vector<std::string> &user_ids, const int nr_of_events)
{
  TUserIdEvents data_extract;

Вместо использования while l oop с объявлением переменной и итерацией вне, вы можете сделать все это за один for l oop:

// Loop which extracts the events based on user IDs  
for (int event_iterator = 0; event_iterator <= nr_of_events; ++event_iterator)

Ваш внутренний while может быть заменен на дальний, основанный на l oop, поэтому вам не нужно отслеживать другой int-итератор:

// Loop which finds specified user id in an event
for (const auto& userIdsOfEvent : eventsOfUserIds[0])
{
    if (check_id(user_ids, userIdsOfEvent))
    {
       for (size_t i = 0; i < eventsOfUserIds.size(); i++)
       {
          data_extract[i].push_back(userIdsOfEvent);
       }
    }
}

Что приводит нас к вашей актуальной проблеме:

data_extract[i].push_back(array[i][user_id_iterator]);

Вы обращаетесь к data_extract с помощью итератора i, но data_extract еще не инициализирован на уровне D1. Для этого вы можете построить его следующим образом:

TUserIdEvents data_extract(eventsOfUserIds.size());

Это создает количество субвекторов в data_extract, равное количеству субвекторов, переданных в качестве параметра.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...