13

We have two vectors of size that depends on runtime and need to check if they are equal - differ elements only after the end of smaller size vector. I used std::equal but the issue is that I need to find first which vector is of smaller size which leads to extra line of code :

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

Can the code to compare two vectors or differ only at the end of smaller vector be improved?

2
  • C++11 only? No C++14 by any chance? Commented Dec 20, 2018 at 8:20
  • 1
    If you don't have an actual problem (like performance requirement your current code does not meet, not necessarily a bug), just want code review, then there is codereview.stackexchange.com Commented Dec 20, 2018 at 14:25

3 Answers 3

23

Since C++14, you can use std::mismatch and check the pair of iterators returned against the end of each range:

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

You also get to know where the elements start to differ, and if they don't, at which point the bigger vector is bigger (the start of the subrange you don't want to compare).

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

2 Comments

The exact semantic information the OP wanted in a single algorithm. +1
Very nice. I did not know that this algorithm existed. +1
8

You only need one call of std::equal if you calculate the smaller size beforehand. I would refactor the code like this:

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

If you need to preserve the second information about which vector is bigger, you could achieve it like this, for instance:

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

4 Comments

I'd suggest using const auto size = std::min(a.size(), a1.size());. This also doesn't perform an unsigned to signed conversion.
Great idea, added it to the post.
The above does not include the 2nd information, e.g. if one of the vector is longer than the other, which the user is distinguishing.
Also possible to eliminate the variable size by doing if (std::equal(a1.begin(), a1.begin() + std::min(a.size(), a1.size()), a.begin())) ...
0

Here is a pure C++11 solution that should work for any sequential container (e.g. std::vector, std::list, std::deque). It uses a custom return type, as the type of comparison you show in the original snippets carries more information than a simple boolean value can incorporate.

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

This can be used like the following and should result in the identical behavior as the code in the question.

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; 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.