C++ STL Interleave two ranges
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
|
show 1 more comment
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
You might be able to beatstd::merge
into doing most of the heavy lifting for you. Unrelated: Don't put stuff into thestd
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 wrotestd::
to indicate that I am looking for a solution in the style of STL. Aboutstd::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
|
show 1 more comment
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
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
c++ stl
edited Nov 16 '18 at 6:18
meguli
asked Nov 16 '18 at 5:54
megulimeguli
510418
510418
You might be able to beatstd::merge
into doing most of the heavy lifting for you. Unrelated: Don't put stuff into thestd
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 wrotestd::
to indicate that I am looking for a solution in the style of STL. Aboutstd::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
|
show 1 more comment
You might be able to beatstd::merge
into doing most of the heavy lifting for you. Unrelated: Don't put stuff into thestd
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 wrotestd::
to indicate that I am looking for a solution in the style of STL. Aboutstd::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
|
show 1 more comment
1 Answer
1
active
oldest
votes
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.
add a comment |
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
add a comment |
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.
add a comment |
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.
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.
edited Nov 16 '18 at 19:08
answered Nov 16 '18 at 7:39
user4581301user4581301
20.9k52033
20.9k52033
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
You might be able to beat
std::merge
into doing most of the heavy lifting for you. Unrelated: Don't put stuff into thestd
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. Aboutstd::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