Intersection of two sorted vectors in C++ Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern) Announcing the arrival of Valued Associate #679: Cesar Manara Unicorn Meta Zoo #1: Why another podcast?A pointer vector sorted by its member functionShould I call a method (i.e. size()) multiple times or store it (if I know the value will not change)Is this implementation of Quicksort good?Computing intersection of 2D infinite linesMerge two already sorted linked listPlace integers into a vector, sum each adjacent pair, refill vector with only the sums of each pair i.e remove all the original data from the vectorMerge two sorted lists of numbersFinding the lowest missing integer in a vector containing negative and positive valuesDemonstration of Scale BalancingType-safe Euclidean vectors in C++

How to mute a string and play another at the same time

Why did Israel vote against lifting the American embargo on Cuba?

Does Prince Arnaud cause someone holding the Princess to lose?

If gravity precedes the formation of a solar system, where did the mass come from that caused the gravity?

Is there a verb for listening stealthily?

What's the difference between using dependency injection with a container and using a service locator?

Is Vivien of the Wilds + Wilderness Reclamation a competitive combo?

FME Console for testing

How to make an animal which can only breed for a certain number of generations?

Married in secret, can marital status in passport be changed at a later date?

Kepler's 3rd law: ratios don't fit data

Weaponising the Grasp-at-a-Distance spell

Normal Operator || T^2|| = ||T||^2

What came first? Venom as the movie or as the song?

What could prevent concentrated local exploration?

What *exactly* is electrical current, voltage, and resistance?

How to know or convert AREA, PERIMETER units in QGIS

What's the connection between Mr. Nancy and fried chicken?

A journey... into the MIND

When does Bran Stark remember Jamie pushing him?

Why do C and C++ allow the expression (int) + 4*5?

Help Recreating a Table

Why does my GNOME settings mention "Moto C Plus"?

Why do people think Winterfell crypts is the safest place for women, children & old people?



Intersection of two sorted vectors in C++



Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern)
Announcing the arrival of Valued Associate #679: Cesar Manara
Unicorn Meta Zoo #1: Why another podcast?A pointer vector sorted by its member functionShould I call a method (i.e. size()) multiple times or store it (if I know the value will not change)Is this implementation of Quicksort good?Computing intersection of 2D infinite linesMerge two already sorted linked listPlace integers into a vector, sum each adjacent pair, refill vector with only the sums of each pair i.e remove all the original data from the vectorMerge two sorted lists of numbersFinding the lowest missing integer in a vector containing negative and positive valuesDemonstration of Scale BalancingType-safe Euclidean vectors in C++



.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








6












$begingroup$


Intersection of two sorted vectors in C++ - can this be written any better?



vector<int> intersection(vector<int>& nums1, vector<int>& nums2) 
vector<int> result;
int l = 0, r = 0;
while(l < nums1.size() && r < nums2.size())
int left = nums1[l], right = nums2[r];
if(left == right)
result.push_back(right);
while(l < nums1.size() && nums1[l] == left )l++;
while(r < nums2.size() && nums2[r] == right )r++;
continue;

if(left < right)
while(l < nums1.size() && nums1[l] == left )l++;
else while( r < nums2.size() && nums2[r] == right )r++;

return result;










share|improve this question











$endgroup$







  • 5




    $begingroup$
    Do you know about std::set_intersection()? Reference and example implementations: en.cppreference.com/w/cpp/algorithm/set_intersection
    $endgroup$
    – user673679
    Apr 4 at 14:30






  • 3




    $begingroup$
    @user673679 yes I did, and didn't want to use it;
    $endgroup$
    – Rick
    Apr 4 at 14:57

















6












$begingroup$


Intersection of two sorted vectors in C++ - can this be written any better?



vector<int> intersection(vector<int>& nums1, vector<int>& nums2) 
vector<int> result;
int l = 0, r = 0;
while(l < nums1.size() && r < nums2.size())
int left = nums1[l], right = nums2[r];
if(left == right)
result.push_back(right);
while(l < nums1.size() && nums1[l] == left )l++;
while(r < nums2.size() && nums2[r] == right )r++;
continue;

if(left < right)
while(l < nums1.size() && nums1[l] == left )l++;
else while( r < nums2.size() && nums2[r] == right )r++;

return result;










share|improve this question











$endgroup$







  • 5




    $begingroup$
    Do you know about std::set_intersection()? Reference and example implementations: en.cppreference.com/w/cpp/algorithm/set_intersection
    $endgroup$
    – user673679
    Apr 4 at 14:30






  • 3




    $begingroup$
    @user673679 yes I did, and didn't want to use it;
    $endgroup$
    – Rick
    Apr 4 at 14:57













6












6








6





$begingroup$


Intersection of two sorted vectors in C++ - can this be written any better?



vector<int> intersection(vector<int>& nums1, vector<int>& nums2) 
vector<int> result;
int l = 0, r = 0;
while(l < nums1.size() && r < nums2.size())
int left = nums1[l], right = nums2[r];
if(left == right)
result.push_back(right);
while(l < nums1.size() && nums1[l] == left )l++;
while(r < nums2.size() && nums2[r] == right )r++;
continue;

if(left < right)
while(l < nums1.size() && nums1[l] == left )l++;
else while( r < nums2.size() && nums2[r] == right )r++;

return result;










share|improve this question











$endgroup$




Intersection of two sorted vectors in C++ - can this be written any better?



vector<int> intersection(vector<int>& nums1, vector<int>& nums2) 
vector<int> result;
int l = 0, r = 0;
while(l < nums1.size() && r < nums2.size())
int left = nums1[l], right = nums2[r];
if(left == right)
result.push_back(right);
while(l < nums1.size() && nums1[l] == left )l++;
while(r < nums2.size() && nums2[r] == right )r++;
continue;

if(left < right)
while(l < nums1.size() && nums1[l] == left )l++;
else while( r < nums2.size() && nums2[r] == right )r++;

return result;







c++ reinventing-the-wheel






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Apr 5 at 1:52









Peter Mortensen

25417




25417










asked Apr 4 at 12:38









RickRick

326112




326112







  • 5




    $begingroup$
    Do you know about std::set_intersection()? Reference and example implementations: en.cppreference.com/w/cpp/algorithm/set_intersection
    $endgroup$
    – user673679
    Apr 4 at 14:30






  • 3




    $begingroup$
    @user673679 yes I did, and didn't want to use it;
    $endgroup$
    – Rick
    Apr 4 at 14:57












  • 5




    $begingroup$
    Do you know about std::set_intersection()? Reference and example implementations: en.cppreference.com/w/cpp/algorithm/set_intersection
    $endgroup$
    – user673679
    Apr 4 at 14:30






  • 3




    $begingroup$
    @user673679 yes I did, and didn't want to use it;
    $endgroup$
    – Rick
    Apr 4 at 14:57







5




5




$begingroup$
Do you know about std::set_intersection()? Reference and example implementations: en.cppreference.com/w/cpp/algorithm/set_intersection
$endgroup$
– user673679
Apr 4 at 14:30




$begingroup$
Do you know about std::set_intersection()? Reference and example implementations: en.cppreference.com/w/cpp/algorithm/set_intersection
$endgroup$
– user673679
Apr 4 at 14:30




3




3




$begingroup$
@user673679 yes I did, and didn't want to use it;
$endgroup$
– Rick
Apr 4 at 14:57




$begingroup$
@user673679 yes I did, and didn't want to use it;
$endgroup$
– Rick
Apr 4 at 14:57










2 Answers
2






active

oldest

votes


















12












$begingroup$


  • Indentation



    Your indentation is not consistent. This makes the code hard to read and maintain. It should be fixed so you don't give other people headaches.



     if(left < right)
    while(l < nums1.size() && nums1[l] == left )l++;
    else while( r < nums2.size() && nums2[r] == right )r++;


    That is basically unreadable giberish (opinion of Martin).




  • Using namespace std; is super bad



    This is mention in nearly every C++ review. There is a large article on the subject here: Why is “using namespace std” considered bad practice?. The second answer is the best in my opinion (Martin) see




  • Multiple declarations in one is bad (thanks to terrible syntax binding rules)



    The one declaration per line has been written about adnausium in best practice guides. Please for the sake of your reader declare one variable per line with its own exact type.



    The syntax binding rules alluded to above is:



    int* x, y; // Here x is int* and y in int
    // confusing to a reader. Did you really mean to make y an int?
    // Avoid this problem be declaring one variable per line



  • Typically, functions like this would be based on iterators to work on any container



    Here your code is limited to only using vectors. But the algorithm you are using could be used by any container type with only small modifications. As a result your function could provide much more utility being written to use iterators.



    The standard library was written such that iterators are the glue between algorithms and container.



  • It would be a lot simpler, if not necessarily more efficient at runtime, to just use some hash sets.


  • This function could be generic in T rather than assuming int.

  • The repeated conditions make me feel like there's simplification waiting here, although exactly what that is eludes me in the two minutes I'm spending on this.

  • Should take by const ref, not ref, so that you can operate on temporaries.





share|improve this answer











$endgroup$








  • 1




    $begingroup$
    You caught the problems and I voted you up, but you could improve your answer by explaining what the issue for the first 4 bullet items.
    $endgroup$
    – pacmaninbw
    Apr 4 at 13:53






  • 2




    $begingroup$
    @pacmaninbw: Added some context.
    $endgroup$
    – Martin York
    Apr 4 at 16:55










  • $begingroup$
    @MartinYork wow! whose answer is it, anyway? :) :) /intended in a positive way/
    $endgroup$
    – Will Ness
    Apr 5 at 8:10


















7












$begingroup$

I invite you to review @DeadMG's answer.



Rewriting following (most of) his advice, you'd get something like:



#include <cassert>
#include <algorithm>
#include <vector>

std::vector<T> intersection(std::vector<T> const& left_vector, std::vector<T> const& right_vector)
auto left = left_vector.begin();
auto left_end = left_vector.end();
auto right = right_vector.begin();
auto right_end = right_vector.end();

assert(std::is_sorted(left, left_end));
assert(std::is_sorted(right, right_end));

std::vector<T> result;

while (left != left_end && right != right_end)
if (*left == *right)
result.push_back(*left);
++left;
++right;
continue;


if (*left < *right)
++left;
continue;


assert(*left > *right);
++right;


return result;



I've always found taking pairs of iterators awkward, so I would not recommend such an interface. Instead, you could take simply take any "iterable", they need not even have the same value type, so long as they are comparable:



template <typename Left, typename Right>
std::vector<typename Left::value_type> intersection(Left const& left_c, Right const& right_c);


Also, note that I've included some assert to validate the pre-conditions of the methods (the collections must be sorted) as well as internal invariants (if *left is neither equal nor strictly less than *right then it must be strictly greater).



I encourage you to use assert liberally:



  • They document intentions: pre-conditions, invariants, etc...

  • They check that those intentions hold.

Documentation & Bug detection rolled in one, with no run-time (Release) cost.






share|improve this answer









$endgroup$








  • 1




    $begingroup$
    Why don't you post that as its own questions. There are some improvements even if we don't move to iterators like using template template types.
    $endgroup$
    – Martin York
    Apr 4 at 16:59






  • 1




    $begingroup$
    @MartinYork: I generally don't find "template template" to be an improvement, they're quite awkward to use, and tend to constrain the inputs more than intended.
    $endgroup$
    – Matthieu M.
    Apr 4 at 17:10










  • $begingroup$
    Accepting iterable types is a good idea, and certainly the direction of modern C++ (Ranges, etc). If I were writing it, I'd probably provide the iterator-pair interface for the rare occasions that the caller needs more control, and provide the range interface as a thin adapter. Also, consider the Standard Library pattern of passing an output iterator - that can similarly be wrapped with an adaptor if a vector result is needed.
    $endgroup$
    – Toby Speight
    Apr 5 at 8:29










  • $begingroup$
    @TobySpeight: If you want two pairs of iterators as input and an output iterator as output... well, that's set_intersection :) Another nice trick, rather than taking an output iterator as argument, would be to create an "intersecting range" which can be consumed lazily and us that to initialize whatever collection you want... haven't played much with ranges yet but it seems doable.
    $endgroup$
    – Matthieu M.
    Apr 5 at 8:35










  • $begingroup$
    I've haven't played with ranges myself, but that does sound like a worthwhile exercise; I'll put that on the list of fun things to do when I get around to it (probably when I need light relief from maintaining C++03 code).
    $endgroup$
    – Toby Speight
    Apr 5 at 8:40











Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f216861%2fintersection-of-two-sorted-vectors-in-c%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









12












$begingroup$


  • Indentation



    Your indentation is not consistent. This makes the code hard to read and maintain. It should be fixed so you don't give other people headaches.



     if(left < right)
    while(l < nums1.size() && nums1[l] == left )l++;
    else while( r < nums2.size() && nums2[r] == right )r++;


    That is basically unreadable giberish (opinion of Martin).




  • Using namespace std; is super bad



    This is mention in nearly every C++ review. There is a large article on the subject here: Why is “using namespace std” considered bad practice?. The second answer is the best in my opinion (Martin) see




  • Multiple declarations in one is bad (thanks to terrible syntax binding rules)



    The one declaration per line has been written about adnausium in best practice guides. Please for the sake of your reader declare one variable per line with its own exact type.



    The syntax binding rules alluded to above is:



    int* x, y; // Here x is int* and y in int
    // confusing to a reader. Did you really mean to make y an int?
    // Avoid this problem be declaring one variable per line



  • Typically, functions like this would be based on iterators to work on any container



    Here your code is limited to only using vectors. But the algorithm you are using could be used by any container type with only small modifications. As a result your function could provide much more utility being written to use iterators.



    The standard library was written such that iterators are the glue between algorithms and container.



  • It would be a lot simpler, if not necessarily more efficient at runtime, to just use some hash sets.


  • This function could be generic in T rather than assuming int.

  • The repeated conditions make me feel like there's simplification waiting here, although exactly what that is eludes me in the two minutes I'm spending on this.

  • Should take by const ref, not ref, so that you can operate on temporaries.





share|improve this answer











$endgroup$








  • 1




    $begingroup$
    You caught the problems and I voted you up, but you could improve your answer by explaining what the issue for the first 4 bullet items.
    $endgroup$
    – pacmaninbw
    Apr 4 at 13:53






  • 2




    $begingroup$
    @pacmaninbw: Added some context.
    $endgroup$
    – Martin York
    Apr 4 at 16:55










  • $begingroup$
    @MartinYork wow! whose answer is it, anyway? :) :) /intended in a positive way/
    $endgroup$
    – Will Ness
    Apr 5 at 8:10















12












$begingroup$


  • Indentation



    Your indentation is not consistent. This makes the code hard to read and maintain. It should be fixed so you don't give other people headaches.



     if(left < right)
    while(l < nums1.size() && nums1[l] == left )l++;
    else while( r < nums2.size() && nums2[r] == right )r++;


    That is basically unreadable giberish (opinion of Martin).




  • Using namespace std; is super bad



    This is mention in nearly every C++ review. There is a large article on the subject here: Why is “using namespace std” considered bad practice?. The second answer is the best in my opinion (Martin) see




  • Multiple declarations in one is bad (thanks to terrible syntax binding rules)



    The one declaration per line has been written about adnausium in best practice guides. Please for the sake of your reader declare one variable per line with its own exact type.



    The syntax binding rules alluded to above is:



    int* x, y; // Here x is int* and y in int
    // confusing to a reader. Did you really mean to make y an int?
    // Avoid this problem be declaring one variable per line



  • Typically, functions like this would be based on iterators to work on any container



    Here your code is limited to only using vectors. But the algorithm you are using could be used by any container type with only small modifications. As a result your function could provide much more utility being written to use iterators.



    The standard library was written such that iterators are the glue between algorithms and container.



  • It would be a lot simpler, if not necessarily more efficient at runtime, to just use some hash sets.


  • This function could be generic in T rather than assuming int.

  • The repeated conditions make me feel like there's simplification waiting here, although exactly what that is eludes me in the two minutes I'm spending on this.

  • Should take by const ref, not ref, so that you can operate on temporaries.





share|improve this answer











$endgroup$








  • 1




    $begingroup$
    You caught the problems and I voted you up, but you could improve your answer by explaining what the issue for the first 4 bullet items.
    $endgroup$
    – pacmaninbw
    Apr 4 at 13:53






  • 2




    $begingroup$
    @pacmaninbw: Added some context.
    $endgroup$
    – Martin York
    Apr 4 at 16:55










  • $begingroup$
    @MartinYork wow! whose answer is it, anyway? :) :) /intended in a positive way/
    $endgroup$
    – Will Ness
    Apr 5 at 8:10













12












12








12





$begingroup$


  • Indentation



    Your indentation is not consistent. This makes the code hard to read and maintain. It should be fixed so you don't give other people headaches.



     if(left < right)
    while(l < nums1.size() && nums1[l] == left )l++;
    else while( r < nums2.size() && nums2[r] == right )r++;


    That is basically unreadable giberish (opinion of Martin).




  • Using namespace std; is super bad



    This is mention in nearly every C++ review. There is a large article on the subject here: Why is “using namespace std” considered bad practice?. The second answer is the best in my opinion (Martin) see




  • Multiple declarations in one is bad (thanks to terrible syntax binding rules)



    The one declaration per line has been written about adnausium in best practice guides. Please for the sake of your reader declare one variable per line with its own exact type.



    The syntax binding rules alluded to above is:



    int* x, y; // Here x is int* and y in int
    // confusing to a reader. Did you really mean to make y an int?
    // Avoid this problem be declaring one variable per line



  • Typically, functions like this would be based on iterators to work on any container



    Here your code is limited to only using vectors. But the algorithm you are using could be used by any container type with only small modifications. As a result your function could provide much more utility being written to use iterators.



    The standard library was written such that iterators are the glue between algorithms and container.



  • It would be a lot simpler, if not necessarily more efficient at runtime, to just use some hash sets.


  • This function could be generic in T rather than assuming int.

  • The repeated conditions make me feel like there's simplification waiting here, although exactly what that is eludes me in the two minutes I'm spending on this.

  • Should take by const ref, not ref, so that you can operate on temporaries.





share|improve this answer











$endgroup$




  • Indentation



    Your indentation is not consistent. This makes the code hard to read and maintain. It should be fixed so you don't give other people headaches.



     if(left < right)
    while(l < nums1.size() && nums1[l] == left )l++;
    else while( r < nums2.size() && nums2[r] == right )r++;


    That is basically unreadable giberish (opinion of Martin).




  • Using namespace std; is super bad



    This is mention in nearly every C++ review. There is a large article on the subject here: Why is “using namespace std” considered bad practice?. The second answer is the best in my opinion (Martin) see




  • Multiple declarations in one is bad (thanks to terrible syntax binding rules)



    The one declaration per line has been written about adnausium in best practice guides. Please for the sake of your reader declare one variable per line with its own exact type.



    The syntax binding rules alluded to above is:



    int* x, y; // Here x is int* and y in int
    // confusing to a reader. Did you really mean to make y an int?
    // Avoid this problem be declaring one variable per line



  • Typically, functions like this would be based on iterators to work on any container



    Here your code is limited to only using vectors. But the algorithm you are using could be used by any container type with only small modifications. As a result your function could provide much more utility being written to use iterators.



    The standard library was written such that iterators are the glue between algorithms and container.



  • It would be a lot simpler, if not necessarily more efficient at runtime, to just use some hash sets.


  • This function could be generic in T rather than assuming int.

  • The repeated conditions make me feel like there's simplification waiting here, although exactly what that is eludes me in the two minutes I'm spending on this.

  • Should take by const ref, not ref, so that you can operate on temporaries.






share|improve this answer














share|improve this answer



share|improve this answer








edited Apr 5 at 2:28









Peter Mortensen

25417




25417










answered Apr 4 at 12:44









DeadMGDeadMG

769612




769612







  • 1




    $begingroup$
    You caught the problems and I voted you up, but you could improve your answer by explaining what the issue for the first 4 bullet items.
    $endgroup$
    – pacmaninbw
    Apr 4 at 13:53






  • 2




    $begingroup$
    @pacmaninbw: Added some context.
    $endgroup$
    – Martin York
    Apr 4 at 16:55










  • $begingroup$
    @MartinYork wow! whose answer is it, anyway? :) :) /intended in a positive way/
    $endgroup$
    – Will Ness
    Apr 5 at 8:10












  • 1




    $begingroup$
    You caught the problems and I voted you up, but you could improve your answer by explaining what the issue for the first 4 bullet items.
    $endgroup$
    – pacmaninbw
    Apr 4 at 13:53






  • 2




    $begingroup$
    @pacmaninbw: Added some context.
    $endgroup$
    – Martin York
    Apr 4 at 16:55










  • $begingroup$
    @MartinYork wow! whose answer is it, anyway? :) :) /intended in a positive way/
    $endgroup$
    – Will Ness
    Apr 5 at 8:10







1




1




$begingroup$
You caught the problems and I voted you up, but you could improve your answer by explaining what the issue for the first 4 bullet items.
$endgroup$
– pacmaninbw
Apr 4 at 13:53




$begingroup$
You caught the problems and I voted you up, but you could improve your answer by explaining what the issue for the first 4 bullet items.
$endgroup$
– pacmaninbw
Apr 4 at 13:53




2




2




$begingroup$
@pacmaninbw: Added some context.
$endgroup$
– Martin York
Apr 4 at 16:55




$begingroup$
@pacmaninbw: Added some context.
$endgroup$
– Martin York
Apr 4 at 16:55












$begingroup$
@MartinYork wow! whose answer is it, anyway? :) :) /intended in a positive way/
$endgroup$
– Will Ness
Apr 5 at 8:10




$begingroup$
@MartinYork wow! whose answer is it, anyway? :) :) /intended in a positive way/
$endgroup$
– Will Ness
Apr 5 at 8:10













7












$begingroup$

I invite you to review @DeadMG's answer.



Rewriting following (most of) his advice, you'd get something like:



#include <cassert>
#include <algorithm>
#include <vector>

std::vector<T> intersection(std::vector<T> const& left_vector, std::vector<T> const& right_vector)
auto left = left_vector.begin();
auto left_end = left_vector.end();
auto right = right_vector.begin();
auto right_end = right_vector.end();

assert(std::is_sorted(left, left_end));
assert(std::is_sorted(right, right_end));

std::vector<T> result;

while (left != left_end && right != right_end)
if (*left == *right)
result.push_back(*left);
++left;
++right;
continue;


if (*left < *right)
++left;
continue;


assert(*left > *right);
++right;


return result;



I've always found taking pairs of iterators awkward, so I would not recommend such an interface. Instead, you could take simply take any "iterable", they need not even have the same value type, so long as they are comparable:



template <typename Left, typename Right>
std::vector<typename Left::value_type> intersection(Left const& left_c, Right const& right_c);


Also, note that I've included some assert to validate the pre-conditions of the methods (the collections must be sorted) as well as internal invariants (if *left is neither equal nor strictly less than *right then it must be strictly greater).



I encourage you to use assert liberally:



  • They document intentions: pre-conditions, invariants, etc...

  • They check that those intentions hold.

Documentation & Bug detection rolled in one, with no run-time (Release) cost.






share|improve this answer









$endgroup$








  • 1




    $begingroup$
    Why don't you post that as its own questions. There are some improvements even if we don't move to iterators like using template template types.
    $endgroup$
    – Martin York
    Apr 4 at 16:59






  • 1




    $begingroup$
    @MartinYork: I generally don't find "template template" to be an improvement, they're quite awkward to use, and tend to constrain the inputs more than intended.
    $endgroup$
    – Matthieu M.
    Apr 4 at 17:10










  • $begingroup$
    Accepting iterable types is a good idea, and certainly the direction of modern C++ (Ranges, etc). If I were writing it, I'd probably provide the iterator-pair interface for the rare occasions that the caller needs more control, and provide the range interface as a thin adapter. Also, consider the Standard Library pattern of passing an output iterator - that can similarly be wrapped with an adaptor if a vector result is needed.
    $endgroup$
    – Toby Speight
    Apr 5 at 8:29










  • $begingroup$
    @TobySpeight: If you want two pairs of iterators as input and an output iterator as output... well, that's set_intersection :) Another nice trick, rather than taking an output iterator as argument, would be to create an "intersecting range" which can be consumed lazily and us that to initialize whatever collection you want... haven't played much with ranges yet but it seems doable.
    $endgroup$
    – Matthieu M.
    Apr 5 at 8:35










  • $begingroup$
    I've haven't played with ranges myself, but that does sound like a worthwhile exercise; I'll put that on the list of fun things to do when I get around to it (probably when I need light relief from maintaining C++03 code).
    $endgroup$
    – Toby Speight
    Apr 5 at 8:40















7












$begingroup$

I invite you to review @DeadMG's answer.



Rewriting following (most of) his advice, you'd get something like:



#include <cassert>
#include <algorithm>
#include <vector>

std::vector<T> intersection(std::vector<T> const& left_vector, std::vector<T> const& right_vector)
auto left = left_vector.begin();
auto left_end = left_vector.end();
auto right = right_vector.begin();
auto right_end = right_vector.end();

assert(std::is_sorted(left, left_end));
assert(std::is_sorted(right, right_end));

std::vector<T> result;

while (left != left_end && right != right_end)
if (*left == *right)
result.push_back(*left);
++left;
++right;
continue;


if (*left < *right)
++left;
continue;


assert(*left > *right);
++right;


return result;



I've always found taking pairs of iterators awkward, so I would not recommend such an interface. Instead, you could take simply take any "iterable", they need not even have the same value type, so long as they are comparable:



template <typename Left, typename Right>
std::vector<typename Left::value_type> intersection(Left const& left_c, Right const& right_c);


Also, note that I've included some assert to validate the pre-conditions of the methods (the collections must be sorted) as well as internal invariants (if *left is neither equal nor strictly less than *right then it must be strictly greater).



I encourage you to use assert liberally:



  • They document intentions: pre-conditions, invariants, etc...

  • They check that those intentions hold.

Documentation & Bug detection rolled in one, with no run-time (Release) cost.






share|improve this answer









$endgroup$








  • 1




    $begingroup$
    Why don't you post that as its own questions. There are some improvements even if we don't move to iterators like using template template types.
    $endgroup$
    – Martin York
    Apr 4 at 16:59






  • 1




    $begingroup$
    @MartinYork: I generally don't find "template template" to be an improvement, they're quite awkward to use, and tend to constrain the inputs more than intended.
    $endgroup$
    – Matthieu M.
    Apr 4 at 17:10










  • $begingroup$
    Accepting iterable types is a good idea, and certainly the direction of modern C++ (Ranges, etc). If I were writing it, I'd probably provide the iterator-pair interface for the rare occasions that the caller needs more control, and provide the range interface as a thin adapter. Also, consider the Standard Library pattern of passing an output iterator - that can similarly be wrapped with an adaptor if a vector result is needed.
    $endgroup$
    – Toby Speight
    Apr 5 at 8:29










  • $begingroup$
    @TobySpeight: If you want two pairs of iterators as input and an output iterator as output... well, that's set_intersection :) Another nice trick, rather than taking an output iterator as argument, would be to create an "intersecting range" which can be consumed lazily and us that to initialize whatever collection you want... haven't played much with ranges yet but it seems doable.
    $endgroup$
    – Matthieu M.
    Apr 5 at 8:35










  • $begingroup$
    I've haven't played with ranges myself, but that does sound like a worthwhile exercise; I'll put that on the list of fun things to do when I get around to it (probably when I need light relief from maintaining C++03 code).
    $endgroup$
    – Toby Speight
    Apr 5 at 8:40













7












7








7





$begingroup$

I invite you to review @DeadMG's answer.



Rewriting following (most of) his advice, you'd get something like:



#include <cassert>
#include <algorithm>
#include <vector>

std::vector<T> intersection(std::vector<T> const& left_vector, std::vector<T> const& right_vector)
auto left = left_vector.begin();
auto left_end = left_vector.end();
auto right = right_vector.begin();
auto right_end = right_vector.end();

assert(std::is_sorted(left, left_end));
assert(std::is_sorted(right, right_end));

std::vector<T> result;

while (left != left_end && right != right_end)
if (*left == *right)
result.push_back(*left);
++left;
++right;
continue;


if (*left < *right)
++left;
continue;


assert(*left > *right);
++right;


return result;



I've always found taking pairs of iterators awkward, so I would not recommend such an interface. Instead, you could take simply take any "iterable", they need not even have the same value type, so long as they are comparable:



template <typename Left, typename Right>
std::vector<typename Left::value_type> intersection(Left const& left_c, Right const& right_c);


Also, note that I've included some assert to validate the pre-conditions of the methods (the collections must be sorted) as well as internal invariants (if *left is neither equal nor strictly less than *right then it must be strictly greater).



I encourage you to use assert liberally:



  • They document intentions: pre-conditions, invariants, etc...

  • They check that those intentions hold.

Documentation & Bug detection rolled in one, with no run-time (Release) cost.






share|improve this answer









$endgroup$



I invite you to review @DeadMG's answer.



Rewriting following (most of) his advice, you'd get something like:



#include <cassert>
#include <algorithm>
#include <vector>

std::vector<T> intersection(std::vector<T> const& left_vector, std::vector<T> const& right_vector)
auto left = left_vector.begin();
auto left_end = left_vector.end();
auto right = right_vector.begin();
auto right_end = right_vector.end();

assert(std::is_sorted(left, left_end));
assert(std::is_sorted(right, right_end));

std::vector<T> result;

while (left != left_end && right != right_end)
if (*left == *right)
result.push_back(*left);
++left;
++right;
continue;


if (*left < *right)
++left;
continue;


assert(*left > *right);
++right;


return result;



I've always found taking pairs of iterators awkward, so I would not recommend such an interface. Instead, you could take simply take any "iterable", they need not even have the same value type, so long as they are comparable:



template <typename Left, typename Right>
std::vector<typename Left::value_type> intersection(Left const& left_c, Right const& right_c);


Also, note that I've included some assert to validate the pre-conditions of the methods (the collections must be sorted) as well as internal invariants (if *left is neither equal nor strictly less than *right then it must be strictly greater).



I encourage you to use assert liberally:



  • They document intentions: pre-conditions, invariants, etc...

  • They check that those intentions hold.

Documentation & Bug detection rolled in one, with no run-time (Release) cost.







share|improve this answer












share|improve this answer



share|improve this answer










answered Apr 4 at 16:55









Matthieu M.Matthieu M.

2,1971810




2,1971810







  • 1




    $begingroup$
    Why don't you post that as its own questions. There are some improvements even if we don't move to iterators like using template template types.
    $endgroup$
    – Martin York
    Apr 4 at 16:59






  • 1




    $begingroup$
    @MartinYork: I generally don't find "template template" to be an improvement, they're quite awkward to use, and tend to constrain the inputs more than intended.
    $endgroup$
    – Matthieu M.
    Apr 4 at 17:10










  • $begingroup$
    Accepting iterable types is a good idea, and certainly the direction of modern C++ (Ranges, etc). If I were writing it, I'd probably provide the iterator-pair interface for the rare occasions that the caller needs more control, and provide the range interface as a thin adapter. Also, consider the Standard Library pattern of passing an output iterator - that can similarly be wrapped with an adaptor if a vector result is needed.
    $endgroup$
    – Toby Speight
    Apr 5 at 8:29










  • $begingroup$
    @TobySpeight: If you want two pairs of iterators as input and an output iterator as output... well, that's set_intersection :) Another nice trick, rather than taking an output iterator as argument, would be to create an "intersecting range" which can be consumed lazily and us that to initialize whatever collection you want... haven't played much with ranges yet but it seems doable.
    $endgroup$
    – Matthieu M.
    Apr 5 at 8:35










  • $begingroup$
    I've haven't played with ranges myself, but that does sound like a worthwhile exercise; I'll put that on the list of fun things to do when I get around to it (probably when I need light relief from maintaining C++03 code).
    $endgroup$
    – Toby Speight
    Apr 5 at 8:40












  • 1




    $begingroup$
    Why don't you post that as its own questions. There are some improvements even if we don't move to iterators like using template template types.
    $endgroup$
    – Martin York
    Apr 4 at 16:59






  • 1




    $begingroup$
    @MartinYork: I generally don't find "template template" to be an improvement, they're quite awkward to use, and tend to constrain the inputs more than intended.
    $endgroup$
    – Matthieu M.
    Apr 4 at 17:10










  • $begingroup$
    Accepting iterable types is a good idea, and certainly the direction of modern C++ (Ranges, etc). If I were writing it, I'd probably provide the iterator-pair interface for the rare occasions that the caller needs more control, and provide the range interface as a thin adapter. Also, consider the Standard Library pattern of passing an output iterator - that can similarly be wrapped with an adaptor if a vector result is needed.
    $endgroup$
    – Toby Speight
    Apr 5 at 8:29










  • $begingroup$
    @TobySpeight: If you want two pairs of iterators as input and an output iterator as output... well, that's set_intersection :) Another nice trick, rather than taking an output iterator as argument, would be to create an "intersecting range" which can be consumed lazily and us that to initialize whatever collection you want... haven't played much with ranges yet but it seems doable.
    $endgroup$
    – Matthieu M.
    Apr 5 at 8:35










  • $begingroup$
    I've haven't played with ranges myself, but that does sound like a worthwhile exercise; I'll put that on the list of fun things to do when I get around to it (probably when I need light relief from maintaining C++03 code).
    $endgroup$
    – Toby Speight
    Apr 5 at 8:40







1




1




$begingroup$
Why don't you post that as its own questions. There are some improvements even if we don't move to iterators like using template template types.
$endgroup$
– Martin York
Apr 4 at 16:59




$begingroup$
Why don't you post that as its own questions. There are some improvements even if we don't move to iterators like using template template types.
$endgroup$
– Martin York
Apr 4 at 16:59




1




1




$begingroup$
@MartinYork: I generally don't find "template template" to be an improvement, they're quite awkward to use, and tend to constrain the inputs more than intended.
$endgroup$
– Matthieu M.
Apr 4 at 17:10




$begingroup$
@MartinYork: I generally don't find "template template" to be an improvement, they're quite awkward to use, and tend to constrain the inputs more than intended.
$endgroup$
– Matthieu M.
Apr 4 at 17:10












$begingroup$
Accepting iterable types is a good idea, and certainly the direction of modern C++ (Ranges, etc). If I were writing it, I'd probably provide the iterator-pair interface for the rare occasions that the caller needs more control, and provide the range interface as a thin adapter. Also, consider the Standard Library pattern of passing an output iterator - that can similarly be wrapped with an adaptor if a vector result is needed.
$endgroup$
– Toby Speight
Apr 5 at 8:29




$begingroup$
Accepting iterable types is a good idea, and certainly the direction of modern C++ (Ranges, etc). If I were writing it, I'd probably provide the iterator-pair interface for the rare occasions that the caller needs more control, and provide the range interface as a thin adapter. Also, consider the Standard Library pattern of passing an output iterator - that can similarly be wrapped with an adaptor if a vector result is needed.
$endgroup$
– Toby Speight
Apr 5 at 8:29












$begingroup$
@TobySpeight: If you want two pairs of iterators as input and an output iterator as output... well, that's set_intersection :) Another nice trick, rather than taking an output iterator as argument, would be to create an "intersecting range" which can be consumed lazily and us that to initialize whatever collection you want... haven't played much with ranges yet but it seems doable.
$endgroup$
– Matthieu M.
Apr 5 at 8:35




$begingroup$
@TobySpeight: If you want two pairs of iterators as input and an output iterator as output... well, that's set_intersection :) Another nice trick, rather than taking an output iterator as argument, would be to create an "intersecting range" which can be consumed lazily and us that to initialize whatever collection you want... haven't played much with ranges yet but it seems doable.
$endgroup$
– Matthieu M.
Apr 5 at 8:35












$begingroup$
I've haven't played with ranges myself, but that does sound like a worthwhile exercise; I'll put that on the list of fun things to do when I get around to it (probably when I need light relief from maintaining C++03 code).
$endgroup$
– Toby Speight
Apr 5 at 8:40




$begingroup$
I've haven't played with ranges myself, but that does sound like a worthwhile exercise; I'll put that on the list of fun things to do when I get around to it (probably when I need light relief from maintaining C++03 code).
$endgroup$
– Toby Speight
Apr 5 at 8:40

















draft saved

draft discarded
















































Thanks for contributing an answer to Code Review Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

Use MathJax to format equations. MathJax reference.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f216861%2fintersection-of-two-sorted-vectors-in-c%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Adding axes to figuresAdding axes labels to LaTeX figuresLaTeX equivalent of ConTeXt buffersRotate a node but not its content: the case of the ellipse decorationHow to define the default vertical distance between nodes?TikZ scaling graphic and adjust node position and keep font sizeNumerical conditional within tikz keys?adding axes to shapesAlign axes across subfiguresAdding figures with a certain orderLine up nested tikz enviroments or how to get rid of themAdding axes labels to LaTeX figures

Luettelo Yhdysvaltain laivaston lentotukialuksista Lähteet | Navigointivalikko

Gary (muusikko) Sisällysluettelo Historia | Rockin' High | Lähteet | Aiheesta muualla | NavigointivalikkoInfobox OKTuomas "Gary" Keskinen Ancaran kitaristiksiProjekti Rockin' High