【问题标题】:Initialize empty vector of vectors with elements of vector of vectors用向量的向量的元素初始化向量的空向量
【发布时间】:2020-02-07 08:23:06
【问题描述】:

我有一个函数,它应该使用来自字符串类型的给定向量向量中的某些元素来初始化来自字符串类型的空向量向量。我的语法是这样的

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 个)。我的方法应在

中搜索某些 UserID
check_id(user_ids, array[0][user_id_iterator])

然后将相关事件(user_id_iterator)推送到所有一维向量的新二维向量中

vector[i:in][user_id_iterator]

进入新发起的向量

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

在 for 循环中。

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

这一切都按预期工作,直到行 [user_id_iterator] 中的向量 [i:in] 的元素被推入 emtpy 向量中。

我最初是否必须初始化 2D Vector data_extract 中的所有 1D 向量?填充向量的空向量的正确语法是什么,其中某些元素来自向量的填充向量? 我收到异常(分段错误),因为 emtpy 向量未正确初始化。

【问题讨论】:

  • 这个函数有点乱。尝试使用更多的 STL 函数。我很确定您可以将 user_id_iterator-loop 替换为:user_id_it = std::find()

标签: c++ c++11 vector


【解决方案1】:

你犯了一个简单的错误,很容易修复。

你的二维向量

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

为空,在定义之后。这意味着,它不包含任何元素,没有维度。甚至不是索引为[0][0][0] 的元素。因此,您遇到了段错误,因为您正在访问不存在的元素 [i]

所以,是的,正如您所假设的,您必须初始化向量。有几种可能性。您可以使用here 中描述的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(),""));

顺便说一句。您的外部 while 循环是无操作的。

while (event_iterator <= nr_of_events)

“event_iterator”在循环体中没有使用,内部的while循环永远不会运行。这是因为在第二轮外循环中,“user_id_iterator”已经比“array[0].size()”大,内循环永远不会运行。

其余的逻辑也很难理解。我不确定,为什么你总是提到“array[0]”。

【讨论】:

    【解决方案2】:

    您的分段错误很难找到,因为您实现的功能过于复杂。有一些简单的重构措施,可以减少这里产生的噪音:

    调用字符串向量的向量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;
    

    您可以在一个 for 循环中完成所有操作,而不是在外部使用带有变量声明和迭代的 while 循环:

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

    您的内部 while 可以替换为基于范围的 for 循环,因此您无需跟踪另一个 int-iterator:

    // 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]);
    

    您正在使用迭代器 i 访问 data_extract,但 data_extract 尚未在 D1 级别初始化。为此,您可以按如下方式构建它:

    TUserIdEvents data_extract(eventsOfUserIds.size());
    

    这会在 data_extract 中创建一定数量的子向量,等于作为参数传递的子向量的数量。

    【讨论】:

      猜你喜欢
      • 2011-03-04
      • 2011-05-18
      • 1970-01-01
      • 2018-09-30
      • 1970-01-01
      • 1970-01-01
      • 2015-09-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多