How to iterate equal values with the standard library?How do you set, clear, and toggle a single bit?How do I iterate over the words of a string?How do I sort a vector of pairs based on the second element of the pair?How can I profile C++ code running on Linux?C++ sorting and keeping track of indexesC++11 introduced a standardized memory model. What does it mean? And how is it going to affect C++ programming?Iterator invalidation rulesHow to implement equal range “iterator”Resize vector given an iterator in C++Most 'functional' way to sum pairs of elements from a vector using C++17 or later?

Why do we need a bootloader separate than our application program in MCU's?

Why do Klingons use cloaking devices?

Can mxd files be under version control?

What is the addition in the re-released version of Avengers: Endgame?

Show that there are infinitely more problems than we will ever be able to compute

Apex Sleep: what is CPU penalty

Taking advantage when the HR forgets to communicate the rules

What is the fundamental difference between catching whales and hunting other animals?

Why did C++11 make std::string::data() add a null terminating character?

Can 4 Joy cons connect to the same Switch?

What is the maximum amount of diamond in one Minecraft game?

Bypass with wrong cvv of debit card and getting OTP

Is it possible that Curiosity measured its own methane or failed doing the spectrometry?

Implementing absolute value function in c

How can I define a very large matrix efficiently?

Can a wizard delay learning new spells from leveling up, and instead learn different spells later?

Could you sell yourself into slavery in the USA?

How can I effectively map a multi-level dungeon?

Do the 26 richest billionaires own as much wealth as the poorest 3.8 billion people?

Does Evolution Sage proliferate Blast Zone when played?

What is this arch-and-tower near a road?

What is the difference between a historical drama and a period drama?

Data normalization before or after train-test split?

What is the name of the technique when an element is repeated at different scales?



How to iterate equal values with the standard library?


How do you set, clear, and toggle a single bit?How do I iterate over the words of a string?How do I sort a vector of pairs based on the second element of the pair?How can I profile C++ code running on Linux?C++ sorting and keeping track of indexesC++11 introduced a standardized memory model. What does it mean? And how is it going to affect C++ programming?Iterator invalidation rulesHow to implement equal range “iterator”Resize vector given an iterator in C++Most 'functional' way to sum pairs of elements from a vector using C++17 or later?






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








8















Suppose that I have a vector of something:



std::vector<Foo> v;


This vector is sorted, so equal elements are next to each other.



What is the best way to get all iterator pairs representing ranges with equal elements (using the standard library)?



while (v-is-not-processed) 
iterator b = <begin-of-next-range-of-equal-elements>;
iterator e = <end-of-next-range-of-equal-elements>;

for (iterator i=b; i!=e; ++i)
// do something with i




I'd like to know, how to get values of b and e in the code above.



So, for example, if v contains these numbers:



 index 0 1 2 3 4 5 6 7 8 9
value 2 2 2 4 6 6 7 7 7 8


Then I'd like to have b and e point to elements in the loop:



 iteration b e
1st 0 3
2nd 3 4
3rd 4 6
4th 6 9
5th 9 10


Is there an elegant way to solve this with the standard library?










share|improve this question

















  • 1





    It should be noted the code in the question is not a good example of how this could be useful. Nothing is done with e other than bounding the inner loop, and the inner loop could just as well be bounded by testing for a new value in element i. So any effort expended finding e serves no purpose (unless computation of the “value” used to sort v is so excessively expensive that a binary search for e would be cheaper than testing each element as we go).

    – Eric Postpischil
    7 hours ago












  • @EricPostpischil: That's true. But even if we don't use e for anything, this formulation is convenient, it's harder to make an error. The other way (to check for changing values) is more tedious (as we need to handle the last range specially - or do you know some tricks to avoid it?).

    – geza
    7 hours ago

















8















Suppose that I have a vector of something:



std::vector<Foo> v;


This vector is sorted, so equal elements are next to each other.



What is the best way to get all iterator pairs representing ranges with equal elements (using the standard library)?



while (v-is-not-processed) 
iterator b = <begin-of-next-range-of-equal-elements>;
iterator e = <end-of-next-range-of-equal-elements>;

for (iterator i=b; i!=e; ++i)
// do something with i




I'd like to know, how to get values of b and e in the code above.



So, for example, if v contains these numbers:



 index 0 1 2 3 4 5 6 7 8 9
value 2 2 2 4 6 6 7 7 7 8


Then I'd like to have b and e point to elements in the loop:



 iteration b e
1st 0 3
2nd 3 4
3rd 4 6
4th 6 9
5th 9 10


Is there an elegant way to solve this with the standard library?










share|improve this question

















  • 1





    It should be noted the code in the question is not a good example of how this could be useful. Nothing is done with e other than bounding the inner loop, and the inner loop could just as well be bounded by testing for a new value in element i. So any effort expended finding e serves no purpose (unless computation of the “value” used to sort v is so excessively expensive that a binary search for e would be cheaper than testing each element as we go).

    – Eric Postpischil
    7 hours ago












  • @EricPostpischil: That's true. But even if we don't use e for anything, this formulation is convenient, it's harder to make an error. The other way (to check for changing values) is more tedious (as we need to handle the last range specially - or do you know some tricks to avoid it?).

    – geza
    7 hours ago













8












8








8


1






Suppose that I have a vector of something:



std::vector<Foo> v;


This vector is sorted, so equal elements are next to each other.



What is the best way to get all iterator pairs representing ranges with equal elements (using the standard library)?



while (v-is-not-processed) 
iterator b = <begin-of-next-range-of-equal-elements>;
iterator e = <end-of-next-range-of-equal-elements>;

for (iterator i=b; i!=e; ++i)
// do something with i




I'd like to know, how to get values of b and e in the code above.



So, for example, if v contains these numbers:



 index 0 1 2 3 4 5 6 7 8 9
value 2 2 2 4 6 6 7 7 7 8


Then I'd like to have b and e point to elements in the loop:



 iteration b e
1st 0 3
2nd 3 4
3rd 4 6
4th 6 9
5th 9 10


Is there an elegant way to solve this with the standard library?










share|improve this question














Suppose that I have a vector of something:



std::vector<Foo> v;


This vector is sorted, so equal elements are next to each other.



What is the best way to get all iterator pairs representing ranges with equal elements (using the standard library)?



while (v-is-not-processed) 
iterator b = <begin-of-next-range-of-equal-elements>;
iterator e = <end-of-next-range-of-equal-elements>;

for (iterator i=b; i!=e; ++i)
// do something with i




I'd like to know, how to get values of b and e in the code above.



So, for example, if v contains these numbers:



 index 0 1 2 3 4 5 6 7 8 9
value 2 2 2 4 6 6 7 7 7 8


Then I'd like to have b and e point to elements in the loop:



 iteration b e
1st 0 3
2nd 3 4
3rd 4 6
4th 6 9
5th 9 10


Is there an elegant way to solve this with the standard library?







c++ c++17






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked 8 hours ago









gezageza

15k3 gold badges34 silver badges87 bronze badges




15k3 gold badges34 silver badges87 bronze badges







  • 1





    It should be noted the code in the question is not a good example of how this could be useful. Nothing is done with e other than bounding the inner loop, and the inner loop could just as well be bounded by testing for a new value in element i. So any effort expended finding e serves no purpose (unless computation of the “value” used to sort v is so excessively expensive that a binary search for e would be cheaper than testing each element as we go).

    – Eric Postpischil
    7 hours ago












  • @EricPostpischil: That's true. But even if we don't use e for anything, this formulation is convenient, it's harder to make an error. The other way (to check for changing values) is more tedious (as we need to handle the last range specially - or do you know some tricks to avoid it?).

    – geza
    7 hours ago












  • 1





    It should be noted the code in the question is not a good example of how this could be useful. Nothing is done with e other than bounding the inner loop, and the inner loop could just as well be bounded by testing for a new value in element i. So any effort expended finding e serves no purpose (unless computation of the “value” used to sort v is so excessively expensive that a binary search for e would be cheaper than testing each element as we go).

    – Eric Postpischil
    7 hours ago












  • @EricPostpischil: That's true. But even if we don't use e for anything, this formulation is convenient, it's harder to make an error. The other way (to check for changing values) is more tedious (as we need to handle the last range specially - or do you know some tricks to avoid it?).

    – geza
    7 hours ago







1




1





It should be noted the code in the question is not a good example of how this could be useful. Nothing is done with e other than bounding the inner loop, and the inner loop could just as well be bounded by testing for a new value in element i. So any effort expended finding e serves no purpose (unless computation of the “value” used to sort v is so excessively expensive that a binary search for e would be cheaper than testing each element as we go).

– Eric Postpischil
7 hours ago






It should be noted the code in the question is not a good example of how this could be useful. Nothing is done with e other than bounding the inner loop, and the inner loop could just as well be bounded by testing for a new value in element i. So any effort expended finding e serves no purpose (unless computation of the “value” used to sort v is so excessively expensive that a binary search for e would be cheaper than testing each element as we go).

– Eric Postpischil
7 hours ago














@EricPostpischil: That's true. But even if we don't use e for anything, this formulation is convenient, it's harder to make an error. The other way (to check for changing values) is more tedious (as we need to handle the last range specially - or do you know some tricks to avoid it?).

– geza
7 hours ago





@EricPostpischil: That's true. But even if we don't use e for anything, this formulation is convenient, it's harder to make an error. The other way (to check for changing values) is more tedious (as we need to handle the last range specially - or do you know some tricks to avoid it?).

– geza
7 hours ago












4 Answers
4






active

oldest

votes


















9














You can use std::upper_bound to get the iterator to the "next" value. Since std::upper_bound returns an iterator to the first element greater than that value provided, if you provide the value of the current element, it will give you an iterator that will be one past the end of the current value. That would give you a loop like



iterator it = v.begin();
while (it != v.end())
iterator b = it;
iterator e = std::upper_bound(it, v.end(), *it);

for (iterator i=b; i!=e; ++i)
// do something with i

it = e; // need this so the loop starts on the next value






share|improve this answer

























  • The only problem is that std::upper_bound does a little bit more, because it has to find the element with binary search. But in my case, this is unneeded.

    – geza
    8 hours ago






  • 2





    This makes sense if the subranges of equal elements are large. If they are small, you waste effort doing a binary search over the entire range, when a linear search could find the next element faster (and with better cache locality).

    – Justin
    8 hours ago






  • 2





    @geza If you want to do a linear traversal instead then you can replace std::upper_bound(it, v.end(), *it); with std::find_if(it, v.end(), [=](auto e) return *it != e; );. Depending on the data this could definitely be faster.

    – NathanOliver
    8 hours ago


















4














This is basically Range v3's group_by: group_by(v, std::equal_to). It doesn't exist in the C++17 standard library, but we can write our own rough equivalent:



template <typename FwdIter, typename BinaryPred, typename ForEach>
void for_each_equal_range(FwdIter first, FwdIter last, BinaryPred is_equal, ForEach f)
while (first != last)
auto next_unequal = std::find_if_not(std::next(first), last,
[&] (auto const& element) return is_equal(*first, element); );

f(first, next_unequal);
first = next_unequal;




Usage:



for_each_equal_range(v.begin(), v.end(), std::equal_to, [&] (auto first, auto last) 
for (; first != last; ++first)
// Do something with each element.

);





share|improve this answer

























  • If you know that these subranges of equal elements are large, you may benefit by probing through some sort of binary search.

    – Justin
    8 hours ago



















3














You are looking for std::equal_range.




Returns a range containing all elements equivalent to value in the
range [first, last).




Something like the following should work. (Untested)



iterator it = v.begin();
while (it != v.end())

auto[b, e] = std::equal_range(it, v.end(), *it);
// do something with [b, e)
it = e; // need for the beginning of next std::equal_range






share|improve this answer




















  • 2





    This does some extra work to find the lower-bound of the range when we know that it's just it, but at that point, we'd be the same as NathanOliver's answer (std::upper_bound instead of std::equal_range).

    – Justin
    7 hours ago







  • 1





    @Justin Agreed. Maybe a slight advantage: less typing due to structured binding possibility.

    – JeJo
    7 hours ago


















0















But even if we don't use e for anything, this formulation is convenient, it's harder to make an error. The other way (to check for changing values) is more tedious (as we need to handle the last range specially [...])




Depends on how you interpret 'handling last range specially':



auto begin = v.begin();
// we might need some initialization for whatever on *begin...
for(Iterator i = begin + 1; ; ++i)



No special handling for last range – solely, possibly needing the initialization code twice...



Nested-loop-approach:



auto begin = v.begin();
for(;;)

// initialize first/next range using *begin
for(Iterator i = begin + 1; ; ++i)


LOOP_EXIT:
// go on
// if nothing left to do in function, we might prefer returning over going to...


More elegant? Admitted, I'm in doubt myself... Both approaches avoid iterating over the same range twice (first for finding the end, then the actual iteration), though. And if we make our own library function from:



template <typename Iterator, typename RangeInitializer, typename ElementHandler>
void iterateOverEqualRanges
(
Iterator begin, Iterator end,
RangeInitializer ri, ElementHandler eh
)

// the one of the two approaches you like better
// or your own variation of...



we could then use it like:



std::vector<...> v;
iterateOverEqualRanges
(
v.begin(), v.end(),
[] (auto begin) /* ... */ ,
[] (auto current) /* ... */
);


Now finally, it looks similiar to e. g. std::for_each, doesn't it?






share|improve this answer



























    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: "1"
    ;
    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: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    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%2fstackoverflow.com%2fquestions%2f56859749%2fhow-to-iterate-equal-values-with-the-standard-library%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    9














    You can use std::upper_bound to get the iterator to the "next" value. Since std::upper_bound returns an iterator to the first element greater than that value provided, if you provide the value of the current element, it will give you an iterator that will be one past the end of the current value. That would give you a loop like



    iterator it = v.begin();
    while (it != v.end())
    iterator b = it;
    iterator e = std::upper_bound(it, v.end(), *it);

    for (iterator i=b; i!=e; ++i)
    // do something with i

    it = e; // need this so the loop starts on the next value






    share|improve this answer

























    • The only problem is that std::upper_bound does a little bit more, because it has to find the element with binary search. But in my case, this is unneeded.

      – geza
      8 hours ago






    • 2





      This makes sense if the subranges of equal elements are large. If they are small, you waste effort doing a binary search over the entire range, when a linear search could find the next element faster (and with better cache locality).

      – Justin
      8 hours ago






    • 2





      @geza If you want to do a linear traversal instead then you can replace std::upper_bound(it, v.end(), *it); with std::find_if(it, v.end(), [=](auto e) return *it != e; );. Depending on the data this could definitely be faster.

      – NathanOliver
      8 hours ago















    9














    You can use std::upper_bound to get the iterator to the "next" value. Since std::upper_bound returns an iterator to the first element greater than that value provided, if you provide the value of the current element, it will give you an iterator that will be one past the end of the current value. That would give you a loop like



    iterator it = v.begin();
    while (it != v.end())
    iterator b = it;
    iterator e = std::upper_bound(it, v.end(), *it);

    for (iterator i=b; i!=e; ++i)
    // do something with i

    it = e; // need this so the loop starts on the next value






    share|improve this answer

























    • The only problem is that std::upper_bound does a little bit more, because it has to find the element with binary search. But in my case, this is unneeded.

      – geza
      8 hours ago






    • 2





      This makes sense if the subranges of equal elements are large. If they are small, you waste effort doing a binary search over the entire range, when a linear search could find the next element faster (and with better cache locality).

      – Justin
      8 hours ago






    • 2





      @geza If you want to do a linear traversal instead then you can replace std::upper_bound(it, v.end(), *it); with std::find_if(it, v.end(), [=](auto e) return *it != e; );. Depending on the data this could definitely be faster.

      – NathanOliver
      8 hours ago













    9












    9








    9







    You can use std::upper_bound to get the iterator to the "next" value. Since std::upper_bound returns an iterator to the first element greater than that value provided, if you provide the value of the current element, it will give you an iterator that will be one past the end of the current value. That would give you a loop like



    iterator it = v.begin();
    while (it != v.end())
    iterator b = it;
    iterator e = std::upper_bound(it, v.end(), *it);

    for (iterator i=b; i!=e; ++i)
    // do something with i

    it = e; // need this so the loop starts on the next value






    share|improve this answer















    You can use std::upper_bound to get the iterator to the "next" value. Since std::upper_bound returns an iterator to the first element greater than that value provided, if you provide the value of the current element, it will give you an iterator that will be one past the end of the current value. That would give you a loop like



    iterator it = v.begin();
    while (it != v.end())
    iterator b = it;
    iterator e = std::upper_bound(it, v.end(), *it);

    for (iterator i=b; i!=e; ++i)
    // do something with i

    it = e; // need this so the loop starts on the next value







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 7 hours ago









    Justin

    14.4k9 gold badges60 silver badges102 bronze badges




    14.4k9 gold badges60 silver badges102 bronze badges










    answered 8 hours ago









    NathanOliverNathanOliver

    107k19 gold badges159 silver badges236 bronze badges




    107k19 gold badges159 silver badges236 bronze badges












    • The only problem is that std::upper_bound does a little bit more, because it has to find the element with binary search. But in my case, this is unneeded.

      – geza
      8 hours ago






    • 2





      This makes sense if the subranges of equal elements are large. If they are small, you waste effort doing a binary search over the entire range, when a linear search could find the next element faster (and with better cache locality).

      – Justin
      8 hours ago






    • 2





      @geza If you want to do a linear traversal instead then you can replace std::upper_bound(it, v.end(), *it); with std::find_if(it, v.end(), [=](auto e) return *it != e; );. Depending on the data this could definitely be faster.

      – NathanOliver
      8 hours ago

















    • The only problem is that std::upper_bound does a little bit more, because it has to find the element with binary search. But in my case, this is unneeded.

      – geza
      8 hours ago






    • 2





      This makes sense if the subranges of equal elements are large. If they are small, you waste effort doing a binary search over the entire range, when a linear search could find the next element faster (and with better cache locality).

      – Justin
      8 hours ago






    • 2





      @geza If you want to do a linear traversal instead then you can replace std::upper_bound(it, v.end(), *it); with std::find_if(it, v.end(), [=](auto e) return *it != e; );. Depending on the data this could definitely be faster.

      – NathanOliver
      8 hours ago
















    The only problem is that std::upper_bound does a little bit more, because it has to find the element with binary search. But in my case, this is unneeded.

    – geza
    8 hours ago





    The only problem is that std::upper_bound does a little bit more, because it has to find the element with binary search. But in my case, this is unneeded.

    – geza
    8 hours ago




    2




    2





    This makes sense if the subranges of equal elements are large. If they are small, you waste effort doing a binary search over the entire range, when a linear search could find the next element faster (and with better cache locality).

    – Justin
    8 hours ago





    This makes sense if the subranges of equal elements are large. If they are small, you waste effort doing a binary search over the entire range, when a linear search could find the next element faster (and with better cache locality).

    – Justin
    8 hours ago




    2




    2





    @geza If you want to do a linear traversal instead then you can replace std::upper_bound(it, v.end(), *it); with std::find_if(it, v.end(), [=](auto e) return *it != e; );. Depending on the data this could definitely be faster.

    – NathanOliver
    8 hours ago





    @geza If you want to do a linear traversal instead then you can replace std::upper_bound(it, v.end(), *it); with std::find_if(it, v.end(), [=](auto e) return *it != e; );. Depending on the data this could definitely be faster.

    – NathanOliver
    8 hours ago













    4














    This is basically Range v3's group_by: group_by(v, std::equal_to). It doesn't exist in the C++17 standard library, but we can write our own rough equivalent:



    template <typename FwdIter, typename BinaryPred, typename ForEach>
    void for_each_equal_range(FwdIter first, FwdIter last, BinaryPred is_equal, ForEach f)
    while (first != last)
    auto next_unequal = std::find_if_not(std::next(first), last,
    [&] (auto const& element) return is_equal(*first, element); );

    f(first, next_unequal);
    first = next_unequal;




    Usage:



    for_each_equal_range(v.begin(), v.end(), std::equal_to, [&] (auto first, auto last) 
    for (; first != last; ++first)
    // Do something with each element.

    );





    share|improve this answer

























    • If you know that these subranges of equal elements are large, you may benefit by probing through some sort of binary search.

      – Justin
      8 hours ago
















    4














    This is basically Range v3's group_by: group_by(v, std::equal_to). It doesn't exist in the C++17 standard library, but we can write our own rough equivalent:



    template <typename FwdIter, typename BinaryPred, typename ForEach>
    void for_each_equal_range(FwdIter first, FwdIter last, BinaryPred is_equal, ForEach f)
    while (first != last)
    auto next_unequal = std::find_if_not(std::next(first), last,
    [&] (auto const& element) return is_equal(*first, element); );

    f(first, next_unequal);
    first = next_unequal;




    Usage:



    for_each_equal_range(v.begin(), v.end(), std::equal_to, [&] (auto first, auto last) 
    for (; first != last; ++first)
    // Do something with each element.

    );





    share|improve this answer

























    • If you know that these subranges of equal elements are large, you may benefit by probing through some sort of binary search.

      – Justin
      8 hours ago














    4












    4








    4







    This is basically Range v3's group_by: group_by(v, std::equal_to). It doesn't exist in the C++17 standard library, but we can write our own rough equivalent:



    template <typename FwdIter, typename BinaryPred, typename ForEach>
    void for_each_equal_range(FwdIter first, FwdIter last, BinaryPred is_equal, ForEach f)
    while (first != last)
    auto next_unequal = std::find_if_not(std::next(first), last,
    [&] (auto const& element) return is_equal(*first, element); );

    f(first, next_unequal);
    first = next_unequal;




    Usage:



    for_each_equal_range(v.begin(), v.end(), std::equal_to, [&] (auto first, auto last) 
    for (; first != last; ++first)
    // Do something with each element.

    );





    share|improve this answer















    This is basically Range v3's group_by: group_by(v, std::equal_to). It doesn't exist in the C++17 standard library, but we can write our own rough equivalent:



    template <typename FwdIter, typename BinaryPred, typename ForEach>
    void for_each_equal_range(FwdIter first, FwdIter last, BinaryPred is_equal, ForEach f)
    while (first != last)
    auto next_unequal = std::find_if_not(std::next(first), last,
    [&] (auto const& element) return is_equal(*first, element); );

    f(first, next_unequal);
    first = next_unequal;




    Usage:



    for_each_equal_range(v.begin(), v.end(), std::equal_to, [&] (auto first, auto last) 
    for (; first != last; ++first)
    // Do something with each element.

    );






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 8 hours ago

























    answered 8 hours ago









    JustinJustin

    14.4k9 gold badges60 silver badges102 bronze badges




    14.4k9 gold badges60 silver badges102 bronze badges












    • If you know that these subranges of equal elements are large, you may benefit by probing through some sort of binary search.

      – Justin
      8 hours ago


















    • If you know that these subranges of equal elements are large, you may benefit by probing through some sort of binary search.

      – Justin
      8 hours ago

















    If you know that these subranges of equal elements are large, you may benefit by probing through some sort of binary search.

    – Justin
    8 hours ago






    If you know that these subranges of equal elements are large, you may benefit by probing through some sort of binary search.

    – Justin
    8 hours ago












    3














    You are looking for std::equal_range.




    Returns a range containing all elements equivalent to value in the
    range [first, last).




    Something like the following should work. (Untested)



    iterator it = v.begin();
    while (it != v.end())

    auto[b, e] = std::equal_range(it, v.end(), *it);
    // do something with [b, e)
    it = e; // need for the beginning of next std::equal_range






    share|improve this answer




















    • 2





      This does some extra work to find the lower-bound of the range when we know that it's just it, but at that point, we'd be the same as NathanOliver's answer (std::upper_bound instead of std::equal_range).

      – Justin
      7 hours ago







    • 1





      @Justin Agreed. Maybe a slight advantage: less typing due to structured binding possibility.

      – JeJo
      7 hours ago















    3














    You are looking for std::equal_range.




    Returns a range containing all elements equivalent to value in the
    range [first, last).




    Something like the following should work. (Untested)



    iterator it = v.begin();
    while (it != v.end())

    auto[b, e] = std::equal_range(it, v.end(), *it);
    // do something with [b, e)
    it = e; // need for the beginning of next std::equal_range






    share|improve this answer




















    • 2





      This does some extra work to find the lower-bound of the range when we know that it's just it, but at that point, we'd be the same as NathanOliver's answer (std::upper_bound instead of std::equal_range).

      – Justin
      7 hours ago







    • 1





      @Justin Agreed. Maybe a slight advantage: less typing due to structured binding possibility.

      – JeJo
      7 hours ago













    3












    3








    3







    You are looking for std::equal_range.




    Returns a range containing all elements equivalent to value in the
    range [first, last).




    Something like the following should work. (Untested)



    iterator it = v.begin();
    while (it != v.end())

    auto[b, e] = std::equal_range(it, v.end(), *it);
    // do something with [b, e)
    it = e; // need for the beginning of next std::equal_range






    share|improve this answer















    You are looking for std::equal_range.




    Returns a range containing all elements equivalent to value in the
    range [first, last).




    Something like the following should work. (Untested)



    iterator it = v.begin();
    while (it != v.end())

    auto[b, e] = std::equal_range(it, v.end(), *it);
    // do something with [b, e)
    it = e; // need for the beginning of next std::equal_range







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 7 hours ago









    Justin

    14.4k9 gold badges60 silver badges102 bronze badges




    14.4k9 gold badges60 silver badges102 bronze badges










    answered 8 hours ago









    JeJoJeJo

    6,7463 gold badges12 silver badges34 bronze badges




    6,7463 gold badges12 silver badges34 bronze badges







    • 2





      This does some extra work to find the lower-bound of the range when we know that it's just it, but at that point, we'd be the same as NathanOliver's answer (std::upper_bound instead of std::equal_range).

      – Justin
      7 hours ago







    • 1





      @Justin Agreed. Maybe a slight advantage: less typing due to structured binding possibility.

      – JeJo
      7 hours ago












    • 2





      This does some extra work to find the lower-bound of the range when we know that it's just it, but at that point, we'd be the same as NathanOliver's answer (std::upper_bound instead of std::equal_range).

      – Justin
      7 hours ago







    • 1





      @Justin Agreed. Maybe a slight advantage: less typing due to structured binding possibility.

      – JeJo
      7 hours ago







    2




    2





    This does some extra work to find the lower-bound of the range when we know that it's just it, but at that point, we'd be the same as NathanOliver's answer (std::upper_bound instead of std::equal_range).

    – Justin
    7 hours ago






    This does some extra work to find the lower-bound of the range when we know that it's just it, but at that point, we'd be the same as NathanOliver's answer (std::upper_bound instead of std::equal_range).

    – Justin
    7 hours ago





    1




    1





    @Justin Agreed. Maybe a slight advantage: less typing due to structured binding possibility.

    – JeJo
    7 hours ago





    @Justin Agreed. Maybe a slight advantage: less typing due to structured binding possibility.

    – JeJo
    7 hours ago











    0















    But even if we don't use e for anything, this formulation is convenient, it's harder to make an error. The other way (to check for changing values) is more tedious (as we need to handle the last range specially [...])




    Depends on how you interpret 'handling last range specially':



    auto begin = v.begin();
    // we might need some initialization for whatever on *begin...
    for(Iterator i = begin + 1; ; ++i)



    No special handling for last range – solely, possibly needing the initialization code twice...



    Nested-loop-approach:



    auto begin = v.begin();
    for(;;)

    // initialize first/next range using *begin
    for(Iterator i = begin + 1; ; ++i)


    LOOP_EXIT:
    // go on
    // if nothing left to do in function, we might prefer returning over going to...


    More elegant? Admitted, I'm in doubt myself... Both approaches avoid iterating over the same range twice (first for finding the end, then the actual iteration), though. And if we make our own library function from:



    template <typename Iterator, typename RangeInitializer, typename ElementHandler>
    void iterateOverEqualRanges
    (
    Iterator begin, Iterator end,
    RangeInitializer ri, ElementHandler eh
    )

    // the one of the two approaches you like better
    // or your own variation of...



    we could then use it like:



    std::vector<...> v;
    iterateOverEqualRanges
    (
    v.begin(), v.end(),
    [] (auto begin) /* ... */ ,
    [] (auto current) /* ... */
    );


    Now finally, it looks similiar to e. g. std::for_each, doesn't it?






    share|improve this answer





























      0















      But even if we don't use e for anything, this formulation is convenient, it's harder to make an error. The other way (to check for changing values) is more tedious (as we need to handle the last range specially [...])




      Depends on how you interpret 'handling last range specially':



      auto begin = v.begin();
      // we might need some initialization for whatever on *begin...
      for(Iterator i = begin + 1; ; ++i)



      No special handling for last range – solely, possibly needing the initialization code twice...



      Nested-loop-approach:



      auto begin = v.begin();
      for(;;)

      // initialize first/next range using *begin
      for(Iterator i = begin + 1; ; ++i)


      LOOP_EXIT:
      // go on
      // if nothing left to do in function, we might prefer returning over going to...


      More elegant? Admitted, I'm in doubt myself... Both approaches avoid iterating over the same range twice (first for finding the end, then the actual iteration), though. And if we make our own library function from:



      template <typename Iterator, typename RangeInitializer, typename ElementHandler>
      void iterateOverEqualRanges
      (
      Iterator begin, Iterator end,
      RangeInitializer ri, ElementHandler eh
      )

      // the one of the two approaches you like better
      // or your own variation of...



      we could then use it like:



      std::vector<...> v;
      iterateOverEqualRanges
      (
      v.begin(), v.end(),
      [] (auto begin) /* ... */ ,
      [] (auto current) /* ... */
      );


      Now finally, it looks similiar to e. g. std::for_each, doesn't it?






      share|improve this answer



























        0












        0








        0








        But even if we don't use e for anything, this formulation is convenient, it's harder to make an error. The other way (to check for changing values) is more tedious (as we need to handle the last range specially [...])




        Depends on how you interpret 'handling last range specially':



        auto begin = v.begin();
        // we might need some initialization for whatever on *begin...
        for(Iterator i = begin + 1; ; ++i)



        No special handling for last range – solely, possibly needing the initialization code twice...



        Nested-loop-approach:



        auto begin = v.begin();
        for(;;)

        // initialize first/next range using *begin
        for(Iterator i = begin + 1; ; ++i)


        LOOP_EXIT:
        // go on
        // if nothing left to do in function, we might prefer returning over going to...


        More elegant? Admitted, I'm in doubt myself... Both approaches avoid iterating over the same range twice (first for finding the end, then the actual iteration), though. And if we make our own library function from:



        template <typename Iterator, typename RangeInitializer, typename ElementHandler>
        void iterateOverEqualRanges
        (
        Iterator begin, Iterator end,
        RangeInitializer ri, ElementHandler eh
        )

        // the one of the two approaches you like better
        // or your own variation of...



        we could then use it like:



        std::vector<...> v;
        iterateOverEqualRanges
        (
        v.begin(), v.end(),
        [] (auto begin) /* ... */ ,
        [] (auto current) /* ... */
        );


        Now finally, it looks similiar to e. g. std::for_each, doesn't it?






        share|improve this answer
















        But even if we don't use e for anything, this formulation is convenient, it's harder to make an error. The other way (to check for changing values) is more tedious (as we need to handle the last range specially [...])




        Depends on how you interpret 'handling last range specially':



        auto begin = v.begin();
        // we might need some initialization for whatever on *begin...
        for(Iterator i = begin + 1; ; ++i)



        No special handling for last range – solely, possibly needing the initialization code twice...



        Nested-loop-approach:



        auto begin = v.begin();
        for(;;)

        // initialize first/next range using *begin
        for(Iterator i = begin + 1; ; ++i)


        LOOP_EXIT:
        // go on
        // if nothing left to do in function, we might prefer returning over going to...


        More elegant? Admitted, I'm in doubt myself... Both approaches avoid iterating over the same range twice (first for finding the end, then the actual iteration), though. And if we make our own library function from:



        template <typename Iterator, typename RangeInitializer, typename ElementHandler>
        void iterateOverEqualRanges
        (
        Iterator begin, Iterator end,
        RangeInitializer ri, ElementHandler eh
        )

        // the one of the two approaches you like better
        // or your own variation of...



        we could then use it like:



        std::vector<...> v;
        iterateOverEqualRanges
        (
        v.begin(), v.end(),
        [] (auto begin) /* ... */ ,
        [] (auto current) /* ... */
        );


        Now finally, it looks similiar to e. g. std::for_each, doesn't it?







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 7 hours ago

























        answered 7 hours ago









        AconcaguaAconcagua

        14.9k3 gold badges24 silver badges46 bronze badges




        14.9k3 gold badges24 silver badges46 bronze badges



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • 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.

            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%2fstackoverflow.com%2fquestions%2f56859749%2fhow-to-iterate-equal-values-with-the-standard-library%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

            Invision Community Contents History See also References External links Navigation menuProprietaryinvisioncommunity.comIPS Community ForumsIPS Community Forumsthis blog entry"License Changes, IP.Board 3.4, and the Future""Interview -- Matt Mecham of Ibforums""CEO Invision Power Board, Matt Mecham Is a Liar, Thief!"IPB License Explanation 1.3, 1.3.1, 2.0, and 2.1ArchivedSecurity Fixes, Updates And Enhancements For IPB 1.3.1Archived"New Demo Accounts - Invision Power Services"the original"New Default Skin"the original"Invision Power Board 3.0.0 and Applications Released"the original"Archived copy"the original"Perpetual licenses being done away with""Release Notes - Invision Power Services""Introducing: IPS Community Suite 4!"Invision Community Release Notes

            Canceling a color specificationRandomly assigning color to Graphics3D objects?Default color for Filling in Mathematica 9Coloring specific elements of sets with a prime modified order in an array plotHow to pick a color differing significantly from the colors already in a given color list?Detection of the text colorColor numbers based on their valueCan color schemes for use with ColorData include opacity specification?My dynamic color schemes

            Ласкавець круглолистий Зміст Опис | Поширення | Галерея | Примітки | Посилання | Навігаційне меню58171138361-22960890446Bupleurum rotundifoliumEuro+Med PlantbasePlants of the World Online — Kew ScienceGermplasm Resources Information Network (GRIN)Ласкавецькн. VI : Літери Ком — Левиправивши або дописавши її