Использование итераторов во вложенном цикле по двум векторам для сопоставления элементов и удаления из векторов - PullRequest
0 голосов
/ 27 ноября 2018

Я хотел использовать следующие циклы для сопоставления элементов из двух векторов, а затем удалить их из векторов:

for(auto it1=left_unprocessed_event_arrays.begin(); it1!=left_unprocessed_event_arrays.end(); ++it1){
  for(auto it2=right_unprocessed_event_arrays.begin(); it2!=right_unprocessed_event_arrays.end(); ++it2){
    if(it1->header.stamp.nsec==it2->header.stamp.nsec){
      matching_event_arrays.push_back({*it1,*it2});
      left_unprocessed_event_arrays.erase(it1);
      right_unprocessed_event_arrays.erase(it2);
    }
  }
}

Затем я понял, что не могу сделать это так, потому что с помощью erase() делает итераторы недействительными.
Поиск решения привел меня к этому .Здесь кто-то предлагает использовать указатель, возвращаемый erase(), а затем увеличивать итератор в скобке else следующим образом:

std::vector<std::string>::iterator iter;
for (iter = m_vPaths.begin(); iter != m_vPaths.end(); ) {
    if (::DeleteFile(iter->c_str()))
        iter = m_vPaths.erase(iter);
    else
        ++iter;
}

Но когда я увеличиваю только во внутреннем цикле, он выиграет 'правильно пройти через внешний цикл.Я изо всех сил пытаюсь понять, как я могу заставить это работать для моего вложенного цикла.
Итак, мой вопрос: как я могу реализовать решение связанного ответа для вложенного цикла?Или, если есть другое / лучшее решение: что это?

Ответы [ 3 ]

0 голосов
/ 27 ноября 2018

Я бы использовал goto для выхода из вложенного цикла следующим образом:

for(auto it1=left_unprocessed_event_arrays.begin();   i1!=left_unprocessed_event_arrays.end();){
  for(auto it2=right_unprocessed_event_arrays.begin(); it2!=right_unprocessed_event_arrays.end();){
    if(it1->header.stamp.nsec==it2->header.stamp.nsec){
      matching_event_arrays.push_back({*it1,*it2});
      it1 = left_unprocessed_event_arrays.erase(it1);
      it2 = right_unprocessed_event_arrays.erase(it2);
      goto next;
    }
    ++it2;
  }
  ++it1;
next:;
}
0 голосов
/ 27 ноября 2018

Использование стандартных алгоритмов проясняет и то, что вы хотите сделать, и упрощает управление (в отличие от goto):

for (auto it1 = left_unprocessed.begin(); it1 != left_unprocessed.end(); )
{
  auto eventsMatch = [&event1 = *it1](const auto& event2) {
    return event1.header.stamp.nsec == event2.header.stamp.nsec;
  };

  auto it2 = std::find_if(right_unprocessed.begin(), right_unprocessed.end(), eventsMatch);

  if (it2 != right_unprocessed.end())
  {
    matching_event_arrays.push_back({*it1, *it2});
    it1 = left_unprocessed.erase(it1);
    right_unprocessed.erase(it2);
  }
  else
  {
    ++it1;
  }
}
0 голосов
/ 27 ноября 2018

Посмотрите на этот пример, может быть, это поможет:

int main()
{
    vector<int> a = { 1, 2, 3, 7, 2 };
    vector<int> b = { 2, 3, 4, 9 };

    auto cmp = [&b](int x) {return std::find(b.begin(), b.end(), x) != b.end();};

    while(1)
    {
        auto it = std::find_if(a.begin(), a.end(), cmp);
        if(it == a.end())
            break;
        auto val = *it;
        a.erase(std::remove(a.begin(), a.end(), val), a.end());
        b.erase(std::remove(b.begin(), b.end(), val), b.end());
    }
}
...