Существует ли стандартный способ сравнения двух диапазонов в C ++? - PullRequest
20 голосов
/ 23 марта 2011

Под диапазоном я подразумеваю пару итераторов.В псевдо C ++:

std::vector<int> v1 = { 1, 2, 3, 4, 5 };
std::vector<int> v2 = { 2, 3, 4 };
if( std::compare_range( v1.begin() + 1, v1.end() - 1, v2.begin(), v2.end() ) {
    std::cout << "Alright\n";
}

compare_range, конечно, функция, которую я ищу.

Отказ от ответственности: Это довольно тривиальная функция для записи, я знаю.Но, как и все программисты, я стараюсь быть ленивым; -)

Ответы [ 4 ]

28 голосов
/ 23 марта 2011

std::equal - это шаблон функции, который вы ищете.

if (std::equal(v1.begin() + 1, v1.end() - 1, v2.begin())
{
    std::cout << "Alright\n";
}

Обратите внимание, что std::equal принимает только три аргумента, а не четыре.

7 голосов
/ 23 марта 2011

Использовать std::equal - он также поддерживает диапазоны.

6 голосов
/ 23 марта 2011

Похоже, что не существует стандартного "однофункционального" метода.Упомянутый std :: equal предполагает, что второй диапазон не короче первого.Например, это может привести к повреждению памяти, когда второй интервал пуст.Он также не дает ответа, когда второй диапазон больше.

Требуется комбинация std :: equal и std :: distance или самописная функция:

template <class InputIterator1, class InputIterator2>
bool safe_equal( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2 )
{
  return ( std::distance( first1, last1 ) == std::distance( first2, last2 ) )
     && std::equal( first1, last1, first2 );
}

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

4 голосов
/ 23 марта 2011

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

Для реальных сравнений я нашел std::lexicographical_compare чтобы быть более полезным, хотя отношения, которые это предполагает порядка, а не эквивалентности. Для эквивалентности, вы можете применить его дважды, например

   !lexicographical_compare(a.begin(), a.end(), b.begin(), b.end())
&& !lexicographical_compare(b.begin(), b.end(), a.begin(), a.end())

но это в значительной степени означает сравнение элементов дважды (если есть разница в самом начале).

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