C++ STL Interleave two ranges










0















I did something to achieve interleaving two ranges. Here is the problem.



Say I have two ranges [a1, b1), call R1 and [a2, b2) call R2. For now, assume their std::distance results are the same, say n. I want to write an algorithm



std::interleave(a1, b1, a2, b2, bool swap)



This will reorder the elements in a way that one element of R2 will be followed an element of R1, through all 2n elements. Depending of the value of swap, it should also be reordered as one element of R1 is followed by an element of R2.



I did this using an additional storage and two for loops. This solution is easy. I could also come up with an in-place solution probably, if I tried a little longer. But what I want is, I want to achieve this thing by assembling algorithms from the STL. How can you solve this problem using STL? It is better if the solution is in-place but I am also open to usage of additional storage, as long as we use algorithms from the STL.



EDIT: The permutation of the elements in the given ranges should not be changed. In other words, this should actually be something like stable_interleave. This is why I couldn't come up with something that uses std::merge.



APPLICATION: One application of this is the conversion of video and image formats from planar to non-planar or semi-planar.










share|improve this question
























  • You might be able to beat std::merge into doing most of the heavy lifting for you. Unrelated: Don't put stuff into the std namespace. There are only a few times you're allowed to and this isn't one of them.

    – user4581301
    Nov 16 '18 at 6:12












  • I just wrote std:: to indicate that I am looking for a solution in the style of STL. About std::merge, I thought about it but my ranges are not sorted and their specific permutation kept unchanged is a requirement for me.

    – meguli
    Nov 16 '18 at 6:14







  • 2





    You can supply a comparator that returns true, false, true, false....

    – user4581301
    Nov 16 '18 at 6:17






  • 2





    Example: ideone.com/6XnYWC

    – user4581301
    Nov 16 '18 at 6:23






  • 1





    boost have zip iterator

    – sp2danny
    Nov 16 '18 at 11:25















0















I did something to achieve interleaving two ranges. Here is the problem.



Say I have two ranges [a1, b1), call R1 and [a2, b2) call R2. For now, assume their std::distance results are the same, say n. I want to write an algorithm



std::interleave(a1, b1, a2, b2, bool swap)



This will reorder the elements in a way that one element of R2 will be followed an element of R1, through all 2n elements. Depending of the value of swap, it should also be reordered as one element of R1 is followed by an element of R2.



I did this using an additional storage and two for loops. This solution is easy. I could also come up with an in-place solution probably, if I tried a little longer. But what I want is, I want to achieve this thing by assembling algorithms from the STL. How can you solve this problem using STL? It is better if the solution is in-place but I am also open to usage of additional storage, as long as we use algorithms from the STL.



EDIT: The permutation of the elements in the given ranges should not be changed. In other words, this should actually be something like stable_interleave. This is why I couldn't come up with something that uses std::merge.



APPLICATION: One application of this is the conversion of video and image formats from planar to non-planar or semi-planar.










share|improve this question
























  • You might be able to beat std::merge into doing most of the heavy lifting for you. Unrelated: Don't put stuff into the std namespace. There are only a few times you're allowed to and this isn't one of them.

    – user4581301
    Nov 16 '18 at 6:12












  • I just wrote std:: to indicate that I am looking for a solution in the style of STL. About std::merge, I thought about it but my ranges are not sorted and their specific permutation kept unchanged is a requirement for me.

    – meguli
    Nov 16 '18 at 6:14







  • 2





    You can supply a comparator that returns true, false, true, false....

    – user4581301
    Nov 16 '18 at 6:17






  • 2





    Example: ideone.com/6XnYWC

    – user4581301
    Nov 16 '18 at 6:23






  • 1





    boost have zip iterator

    – sp2danny
    Nov 16 '18 at 11:25













0












0








0








I did something to achieve interleaving two ranges. Here is the problem.



Say I have two ranges [a1, b1), call R1 and [a2, b2) call R2. For now, assume their std::distance results are the same, say n. I want to write an algorithm



std::interleave(a1, b1, a2, b2, bool swap)



This will reorder the elements in a way that one element of R2 will be followed an element of R1, through all 2n elements. Depending of the value of swap, it should also be reordered as one element of R1 is followed by an element of R2.



I did this using an additional storage and two for loops. This solution is easy. I could also come up with an in-place solution probably, if I tried a little longer. But what I want is, I want to achieve this thing by assembling algorithms from the STL. How can you solve this problem using STL? It is better if the solution is in-place but I am also open to usage of additional storage, as long as we use algorithms from the STL.



EDIT: The permutation of the elements in the given ranges should not be changed. In other words, this should actually be something like stable_interleave. This is why I couldn't come up with something that uses std::merge.



APPLICATION: One application of this is the conversion of video and image formats from planar to non-planar or semi-planar.










share|improve this question
















I did something to achieve interleaving two ranges. Here is the problem.



Say I have two ranges [a1, b1), call R1 and [a2, b2) call R2. For now, assume their std::distance results are the same, say n. I want to write an algorithm



std::interleave(a1, b1, a2, b2, bool swap)



This will reorder the elements in a way that one element of R2 will be followed an element of R1, through all 2n elements. Depending of the value of swap, it should also be reordered as one element of R1 is followed by an element of R2.



I did this using an additional storage and two for loops. This solution is easy. I could also come up with an in-place solution probably, if I tried a little longer. But what I want is, I want to achieve this thing by assembling algorithms from the STL. How can you solve this problem using STL? It is better if the solution is in-place but I am also open to usage of additional storage, as long as we use algorithms from the STL.



EDIT: The permutation of the elements in the given ranges should not be changed. In other words, this should actually be something like stable_interleave. This is why I couldn't come up with something that uses std::merge.



APPLICATION: One application of this is the conversion of video and image formats from planar to non-planar or semi-planar.







c++ stl






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 16 '18 at 6:18







meguli

















asked Nov 16 '18 at 5:54









megulimeguli

510418




510418












  • You might be able to beat std::merge into doing most of the heavy lifting for you. Unrelated: Don't put stuff into the std namespace. There are only a few times you're allowed to and this isn't one of them.

    – user4581301
    Nov 16 '18 at 6:12












  • I just wrote std:: to indicate that I am looking for a solution in the style of STL. About std::merge, I thought about it but my ranges are not sorted and their specific permutation kept unchanged is a requirement for me.

    – meguli
    Nov 16 '18 at 6:14







  • 2





    You can supply a comparator that returns true, false, true, false....

    – user4581301
    Nov 16 '18 at 6:17






  • 2





    Example: ideone.com/6XnYWC

    – user4581301
    Nov 16 '18 at 6:23






  • 1





    boost have zip iterator

    – sp2danny
    Nov 16 '18 at 11:25

















  • You might be able to beat std::merge into doing most of the heavy lifting for you. Unrelated: Don't put stuff into the std namespace. There are only a few times you're allowed to and this isn't one of them.

    – user4581301
    Nov 16 '18 at 6:12












  • I just wrote std:: to indicate that I am looking for a solution in the style of STL. About std::merge, I thought about it but my ranges are not sorted and their specific permutation kept unchanged is a requirement for me.

    – meguli
    Nov 16 '18 at 6:14







  • 2





    You can supply a comparator that returns true, false, true, false....

    – user4581301
    Nov 16 '18 at 6:17






  • 2





    Example: ideone.com/6XnYWC

    – user4581301
    Nov 16 '18 at 6:23






  • 1





    boost have zip iterator

    – sp2danny
    Nov 16 '18 at 11:25
















You might be able to beat std::merge into doing most of the heavy lifting for you. Unrelated: Don't put stuff into the std namespace. There are only a few times you're allowed to and this isn't one of them.

– user4581301
Nov 16 '18 at 6:12






You might be able to beat std::merge into doing most of the heavy lifting for you. Unrelated: Don't put stuff into the std namespace. There are only a few times you're allowed to and this isn't one of them.

– user4581301
Nov 16 '18 at 6:12














I just wrote std:: to indicate that I am looking for a solution in the style of STL. About std::merge, I thought about it but my ranges are not sorted and their specific permutation kept unchanged is a requirement for me.

– meguli
Nov 16 '18 at 6:14






I just wrote std:: to indicate that I am looking for a solution in the style of STL. About std::merge, I thought about it but my ranges are not sorted and their specific permutation kept unchanged is a requirement for me.

– meguli
Nov 16 '18 at 6:14





2




2





You can supply a comparator that returns true, false, true, false....

– user4581301
Nov 16 '18 at 6:17





You can supply a comparator that returns true, false, true, false....

– user4581301
Nov 16 '18 at 6:17




2




2





Example: ideone.com/6XnYWC

– user4581301
Nov 16 '18 at 6:23





Example: ideone.com/6XnYWC

– user4581301
Nov 16 '18 at 6:23




1




1





boost have zip iterator

– sp2danny
Nov 16 '18 at 11:25





boost have zip iterator

– sp2danny
Nov 16 '18 at 11:25












1 Answer
1






active

oldest

votes


















1














My pitch of using std::merge can fail. I'm not creative enough to see why anyone would write merge so that it could, but it is violating the requirements for Compare as pointed out in the comments below, so someone could.



Regardless, merge is an overkill solution. It is fewer lines of code hiding extra effort because merge's intended usage is for a more complicated job than we do here.



Example:



#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>
#include <list>
#include <deque>

template<typename IN1,
typename IN2,
typename OUT>
inline OUT interleave(IN1 it1,
IN1 end1,
IN2 it2,
IN2 end2,
OUT out)

// interleave until at least one container is done
while (it1 != end1 && it2 != end2)

// insert from container 1
*out = *it1;
out++;
it1++;
// insert from container 2
*out = *it2;
out++;
it2++;

if (it1 != end1) // check and finish container 1

return std::copy (it1, end1, out);

else if (it2 != end2)// check and finish container 2

return std::copy (it2, end2, out);

return out; // both done


int main()

// fill the containers with numbers
std::vector<int> in1 = 1,3,5,7,9;
std::list<int> in2 = 8,6,4,2;

// construct output container of sufficient size.
// Could also use empty container and *_inserter
std::deque<int> out(in1.size() + in2.size());

// Container-agnostic. reads from vector and list and stores in deque
interleave(in1.begin(), in1.end(),
in2.begin(), in2.end(),
out.begin());
for (int val: out)

std::cout << val << ' ';




Note: rather than implementing with an option to swap the order of the inputs and making all users of interleave pay for it, the caller should call with the order of input parameters reversed.






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%2f53332186%2fc-stl-interleave-two-ranges%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    My pitch of using std::merge can fail. I'm not creative enough to see why anyone would write merge so that it could, but it is violating the requirements for Compare as pointed out in the comments below, so someone could.



    Regardless, merge is an overkill solution. It is fewer lines of code hiding extra effort because merge's intended usage is for a more complicated job than we do here.



    Example:



    #include <iostream>
    #include <iterator>
    #include <algorithm>
    #include <vector>
    #include <list>
    #include <deque>

    template<typename IN1,
    typename IN2,
    typename OUT>
    inline OUT interleave(IN1 it1,
    IN1 end1,
    IN2 it2,
    IN2 end2,
    OUT out)

    // interleave until at least one container is done
    while (it1 != end1 && it2 != end2)

    // insert from container 1
    *out = *it1;
    out++;
    it1++;
    // insert from container 2
    *out = *it2;
    out++;
    it2++;

    if (it1 != end1) // check and finish container 1

    return std::copy (it1, end1, out);

    else if (it2 != end2)// check and finish container 2

    return std::copy (it2, end2, out);

    return out; // both done


    int main()

    // fill the containers with numbers
    std::vector<int> in1 = 1,3,5,7,9;
    std::list<int> in2 = 8,6,4,2;

    // construct output container of sufficient size.
    // Could also use empty container and *_inserter
    std::deque<int> out(in1.size() + in2.size());

    // Container-agnostic. reads from vector and list and stores in deque
    interleave(in1.begin(), in1.end(),
    in2.begin(), in2.end(),
    out.begin());
    for (int val: out)

    std::cout << val << ' ';




    Note: rather than implementing with an option to swap the order of the inputs and making all users of interleave pay for it, the caller should call with the order of input parameters reversed.






    share|improve this answer





























      1














      My pitch of using std::merge can fail. I'm not creative enough to see why anyone would write merge so that it could, but it is violating the requirements for Compare as pointed out in the comments below, so someone could.



      Regardless, merge is an overkill solution. It is fewer lines of code hiding extra effort because merge's intended usage is for a more complicated job than we do here.



      Example:



      #include <iostream>
      #include <iterator>
      #include <algorithm>
      #include <vector>
      #include <list>
      #include <deque>

      template<typename IN1,
      typename IN2,
      typename OUT>
      inline OUT interleave(IN1 it1,
      IN1 end1,
      IN2 it2,
      IN2 end2,
      OUT out)

      // interleave until at least one container is done
      while (it1 != end1 && it2 != end2)

      // insert from container 1
      *out = *it1;
      out++;
      it1++;
      // insert from container 2
      *out = *it2;
      out++;
      it2++;

      if (it1 != end1) // check and finish container 1

      return std::copy (it1, end1, out);

      else if (it2 != end2)// check and finish container 2

      return std::copy (it2, end2, out);

      return out; // both done


      int main()

      // fill the containers with numbers
      std::vector<int> in1 = 1,3,5,7,9;
      std::list<int> in2 = 8,6,4,2;

      // construct output container of sufficient size.
      // Could also use empty container and *_inserter
      std::deque<int> out(in1.size() + in2.size());

      // Container-agnostic. reads from vector and list and stores in deque
      interleave(in1.begin(), in1.end(),
      in2.begin(), in2.end(),
      out.begin());
      for (int val: out)

      std::cout << val << ' ';




      Note: rather than implementing with an option to swap the order of the inputs and making all users of interleave pay for it, the caller should call with the order of input parameters reversed.






      share|improve this answer



























        1












        1








        1







        My pitch of using std::merge can fail. I'm not creative enough to see why anyone would write merge so that it could, but it is violating the requirements for Compare as pointed out in the comments below, so someone could.



        Regardless, merge is an overkill solution. It is fewer lines of code hiding extra effort because merge's intended usage is for a more complicated job than we do here.



        Example:



        #include <iostream>
        #include <iterator>
        #include <algorithm>
        #include <vector>
        #include <list>
        #include <deque>

        template<typename IN1,
        typename IN2,
        typename OUT>
        inline OUT interleave(IN1 it1,
        IN1 end1,
        IN2 it2,
        IN2 end2,
        OUT out)

        // interleave until at least one container is done
        while (it1 != end1 && it2 != end2)

        // insert from container 1
        *out = *it1;
        out++;
        it1++;
        // insert from container 2
        *out = *it2;
        out++;
        it2++;

        if (it1 != end1) // check and finish container 1

        return std::copy (it1, end1, out);

        else if (it2 != end2)// check and finish container 2

        return std::copy (it2, end2, out);

        return out; // both done


        int main()

        // fill the containers with numbers
        std::vector<int> in1 = 1,3,5,7,9;
        std::list<int> in2 = 8,6,4,2;

        // construct output container of sufficient size.
        // Could also use empty container and *_inserter
        std::deque<int> out(in1.size() + in2.size());

        // Container-agnostic. reads from vector and list and stores in deque
        interleave(in1.begin(), in1.end(),
        in2.begin(), in2.end(),
        out.begin());
        for (int val: out)

        std::cout << val << ' ';




        Note: rather than implementing with an option to swap the order of the inputs and making all users of interleave pay for it, the caller should call with the order of input parameters reversed.






        share|improve this answer















        My pitch of using std::merge can fail. I'm not creative enough to see why anyone would write merge so that it could, but it is violating the requirements for Compare as pointed out in the comments below, so someone could.



        Regardless, merge is an overkill solution. It is fewer lines of code hiding extra effort because merge's intended usage is for a more complicated job than we do here.



        Example:



        #include <iostream>
        #include <iterator>
        #include <algorithm>
        #include <vector>
        #include <list>
        #include <deque>

        template<typename IN1,
        typename IN2,
        typename OUT>
        inline OUT interleave(IN1 it1,
        IN1 end1,
        IN2 it2,
        IN2 end2,
        OUT out)

        // interleave until at least one container is done
        while (it1 != end1 && it2 != end2)

        // insert from container 1
        *out = *it1;
        out++;
        it1++;
        // insert from container 2
        *out = *it2;
        out++;
        it2++;

        if (it1 != end1) // check and finish container 1

        return std::copy (it1, end1, out);

        else if (it2 != end2)// check and finish container 2

        return std::copy (it2, end2, out);

        return out; // both done


        int main()

        // fill the containers with numbers
        std::vector<int> in1 = 1,3,5,7,9;
        std::list<int> in2 = 8,6,4,2;

        // construct output container of sufficient size.
        // Could also use empty container and *_inserter
        std::deque<int> out(in1.size() + in2.size());

        // Container-agnostic. reads from vector and list and stores in deque
        interleave(in1.begin(), in1.end(),
        in2.begin(), in2.end(),
        out.begin());
        for (int val: out)

        std::cout << val << ' ';




        Note: rather than implementing with an option to swap the order of the inputs and making all users of interleave pay for it, the caller should call with the order of input parameters reversed.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 16 '18 at 19:08

























        answered Nov 16 '18 at 7:39









        user4581301user4581301

        20.9k52033




        20.9k52033





























            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%2f53332186%2fc-stl-interleave-two-ranges%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

            Top Tejano songwriter Luis Silva dead of heart attack at 64

            ReactJS Fetched API data displays live - need Data displayed static

            Evgeni Malkin