33

By range I mean a pair of iterators. In pseudo 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 being of course the function I'm looking for.

Disclaimer: This is a pretty trivial function to write, I know. But like all programmers, I try to be lazy ;-)

2
  • 6
    Compare how? For equality? Equivalence? Inequality? Higher? Lower? Hotter? Colder? Greener? Bluer? ... Commented Mar 23, 2011 at 12:31
  • 4
    @Tomalak Geret'kal: You forgot "better". Commented Mar 23, 2011 at 12:44

6 Answers 6

38

std::equal is the function template you are looking for.

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

Note that std::equal only takes three arguments, not four.

Sign up to request clarification or add additional context in comments.

6 Comments

Had somehow missed it. Thanks. Now that I've thought about, I obviously don't need that fourth argument... :)
This method is fine, when user guarantees, that both intervals are of the same length. Otherwise it may crash, or work incorrectly.
@Konstantin Tenzin: you've probably meant "that second interval is at least as long as first one"
@Alexander Poluektov: When second interval is larger than the second, method std::equal will qualify it as equal to the first: for example for input {1,2,3}; {1,2,3,4}. This may be not desired for some applications
C++14 adds the 4 argument version, ranges of different lengths return false.
|
7

Use std::equal - it supports ranges as well.

Comments

7

If you have a means of determining that the two ranges have exactly the same number of elements, std::equal will do. In practice, this doesn't seem to be the case that often for me, and most of the uses I have of std::equal are in fact determining whether one range is a prefix of the other.

For actual comparisons, I've found std::lexicographical_compare to be more useful, although the relationship it promesses is one of order, not of equivalence. For equivalence, you can apply it twice, e.g.

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

but this pretty much means comparing elements twice (unless there is a difference right at the beginning).

1 Comment

This is very mathematical and insightful. When element comparison is relatively cheap, and range sizes are expensive (e.g. only forward iterators) - then there is little objection for this elegant idiom. (Of course, a 4-argument version of std::equal, which would also check if both ranges hit their end() at the same time, would still be even better)
6

Is seems, that there is no standard "one-function" method. Mentioned std::equal assumes, that second range is not shorter than the first. For example, this may lead to memory corruption, when second interval is empty. It also does not give answer, when second range is larger.

Combination of std::equal and std::distance is required, or self-written function:

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 );
}

Function above may traverse containter twice for not Random Access Iterators, but uses standard functions. It may be reasonable to write own implementation, if this is not acceptable.

1 Comment

Small syntax fixes: last argument must be called last2 instead of second2 and first open parenthesis after && is redundant.
3

With C++20:

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

or, if less/greater-check is required:

if (auto cmp = std::lexicographical_compare_three_way(v1.begin() + 1, v1.end() - 1, v2.begin(), v2.end()); cmp == 0) {
    std::cout << "Alright\n";
}
else if (cmp < 0) {//...}

std::vector is a contiguous container so additional range-size-check is unnecessary for STL algorithms.

Comments

1

There is a function in Boost which checks also the size of the ranges:

boost::range::equal

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.