Сравните меньший вектор с большим, чтобы проверить, отличается ли он в конце меньшего

У нас есть два вектора размера, которые зависят от времени выполнения, и нам нужно проверить, равны ли они - элементы различаются только после окончания вектора меньшего размера. Я использовал std :: equal, но проблема в том, что мне нужно сначала найти какой вектор имеет меньший размер, что приводит к дополнительной строке кода:

#include <vector>
#include <iostream>

int main()
{
  std::vector<int> a(1000, 3);
  std::vector<int> a1(100, 3);

  if(a.size() > a1.size())
  {
    if(std::equal(a1.begin(), a1.end(), a.begin()))
    {
      std::cout << "Same a gt a1" << std::endl;
    }
  }

  if(a1.size() > a.size())
  {
    if(std::equal(a.begin(), a.end(), a1.begin()))
    {
      std::cout << "Same a1 gt a" << std::endl;
    }
  }

  if(a1.size() == a.size())
  {
    if(std::equal(a.begin(), a.end(), a1.begin()))
    {
       std::cout << "Same a = a1" << std::endl;
    }
  }
}

Может ли быть улучшен код для сравнения двух векторов или отличаться только в конце меньшего вектора?

Ответы

Ответ 1

Вам нужен только один вызов std::equal если вы заранее вычислили меньший размер. Я бы рефакторинг кода, как это:

#include <vector>
#include <iostream>
#include <algorithm>

int main()
{
    std::vector<int> a(1000, 3);
    std::vector<int> a1(100, 3);

    if (std::equal(a1.begin(), a1.begin() + std::min(a.size(), a1.size()), a.begin())) 
    {
        std::cout << "Same" << std::endl;
    }
    return 0;
}

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

std::cout << "Same " << ((a.size() == a1.size())? "a = a1" : ((a.size() > a1.size())? "a gt a1" : "a1 gt a")) << std::endl;

Ответ 2

Начиная с С++ 14, вы можете использовать std::mismatch и проверять пару итераторов, возвращаемых в конце каждого диапазона:

auto it = std::mismatch(a.begin(), a.end(), a1.begin(), a1.end());
if (it.first == a.end() || it.second == a1.end()) {
    // Equality
}

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

Ответ 3

Поскольку С++ 14 std::equal имеет другую перегрузку, которая может обрабатывать другой размер, вам просто нужно написать:

std::equal(a.begin(), a.end(), a1.begin(), a1.end());

cppreference

5-8) Если длина диапазона [first1, last1) не равна длине диапазона [first2, last2), возвращает false

Ответ 4

Вот чистое решение С++ 11, которое должно работать для любого последовательного контейнера (например, std::vector, std::list, std::deque). Он использует пользовательский тип возвращаемого значения, так как тип сравнения, который вы показываете в исходных фрагментах, содержит больше информации, чем может содержать простое логическое значение.

enum class CombinedCompareResult {
   NotEqual, EqualAndFirstLarger, EqualAndSecondLarger, EqualIncludingSize
};

template <class Rng1, class Rng2>
CombinedCompareResult combinedCompare(const Rng1& rng1, const Rng2& rng2)
{
   using std::begin;

   const auto elementsToCompare = std::min(rng1.size(), rng2.size());

   if (!std::equal(begin(rng1), std::next(begin(rng1), elementsToCompare), begin(rng2)))
      return CombinedCompareResult::NotEqual;
   else if (rng1.size() == rng2.size())
      return CombinedCompareResult::EqualIncludingSize;
   else if (rng1.size() > rng2.size())
      return CombinedCompareResult::EqualAndFirstLarger;
   else
      return CombinedCompareResult::EqualAndSecondLarger;
}

Это может быть использовано следующим образом и должно привести к тому же поведению, что и код в вопросе.

const auto cmp = combinedCompare(lst, a);

if (cmp == CombinedCompareResult::EqualIncludingSize)
    std::cout << "Same a = a1" << std::endl;
else if (cmp == CombinedCompareResult::EqualAndFirstLarger)
    std::cout << "Same a gt a1" << std::endl;
else if (cmp == CombinedCompareResult::EqualAndSecondLarger)
    std::cout << "Same a1 gt a" << std::endl;