admin管理员组文章数量:1304921
I have a vector of data of n
elements. I want to print n
vectors of n-1
elements where each of these vectors are the original vector data minus 1 element. Basically, it's a jackknife analysis.
For a data vector containing [ 0 1 2 3 ]
, I want to print the following jackedData vectors:
[ 1 2 3 ]
[ 0 2 3 ]
[ 0 1 3 ]
[ 0 1 2 ]
I've come up with the following:
int Gen()
{
static int i( 0 );
return i++;
}
void Print( const int& i )
{
std::cout << i << " ";
}
int _tmain(int argc, _TCHAR* argv[])
{
std::vector< int > data;
std::generate_n( std::back_inserter( data ), 6, Gen );
std::vector< int > jackedData( data.begin() + 1, data.end() );
std::vector< int >::const_iterator it_data( data.begin() );
std::vector< int >::iterator it_jData( jackedData.begin() );
int i( 0 );
for (
; it_jData != jackedData.end()
; ++it_data, ++it_jData, ++i )
{
std::cout << i << "\t";
std::for_each( jackedData.begin(), jackedData.end(), Print );
std::cout << "\n";
*it_jData = *it_data;
}
std::cout << i << "\t";
std::for_each( jackedData.begin(), jackedData.end(), Print );
std::cout << "\n";
return 0;
}
The problem is, the print has to be called once outside the loop. If it's not called outside the loop, then there is an off-by-one error.
How can this be done without having to call the print once outside of the loop?
I have a vector of data of n
elements. I want to print n
vectors of n-1
elements where each of these vectors are the original vector data minus 1 element. Basically, it's a jackknife analysis.
For a data vector containing [ 0 1 2 3 ]
, I want to print the following jackedData vectors:
[ 1 2 3 ]
[ 0 2 3 ]
[ 0 1 3 ]
[ 0 1 2 ]
I've come up with the following:
int Gen()
{
static int i( 0 );
return i++;
}
void Print( const int& i )
{
std::cout << i << " ";
}
int _tmain(int argc, _TCHAR* argv[])
{
std::vector< int > data;
std::generate_n( std::back_inserter( data ), 6, Gen );
std::vector< int > jackedData( data.begin() + 1, data.end() );
std::vector< int >::const_iterator it_data( data.begin() );
std::vector< int >::iterator it_jData( jackedData.begin() );
int i( 0 );
for (
; it_jData != jackedData.end()
; ++it_data, ++it_jData, ++i )
{
std::cout << i << "\t";
std::for_each( jackedData.begin(), jackedData.end(), Print );
std::cout << "\n";
*it_jData = *it_data;
}
std::cout << i << "\t";
std::for_each( jackedData.begin(), jackedData.end(), Print );
std::cout << "\n";
return 0;
}
The problem is, the print has to be called once outside the loop. If it's not called outside the loop, then there is an off-by-one error.
How can this be done without having to call the print once outside of the loop?
Share Improve this question edited Feb 4 at 4:22 H.S. 12.7k2 gold badges16 silver badges34 bronze badges asked Feb 3 at 21:11 SokaekaeSokaekae 53 bronze badges5 Answers
Reset to default 3#include <iostream>
#include <vector>
//prints the specified range from first (inclusive) to last (exclusive)
void print_range(const int *first, const int *last)
{
for (; first < last ;) {
std::cout << ' ' << *first++;
}
}
int main()
{
std::vector<int> v = {0, 1, 2, 3}; //example vector
for (size_t i=0; i < v.size(); ++i) { //for each element
std::cout << '['; //start of line
//print the range before i [0, i]
print_range(
v.data(), //index: 0 (inclusive)
v.data() + i //index: i (exclusive)
);
//print the range after i [i+1, v.size()]
print_range(
v.data() + i + 1, //index: i+1 (inclusive)
v.data() + v.size() //index: n (exclusive)
);
std::cout << " ]\n"; //end of line
}
}
Note: there are two special cases,
i == 0
- first call to
print_range
will do nothing (first == last == 0
)
- first call to
i == v.size() - 1
- second call to
print_range
will do nothing (first == last == v.size()
)
- second call to
There is no need to test these cases separately, since the comparison is already done in print_range
(first < last
).
If its allowed to modify the input vector, you can do this -
Iterate over vector of size n
in a loop and in every iteration:
- Print the last
n - 1
elements of vector. - After this, swap the first element with element at position -
current processing vector index + 1
.
Implementation:
#include <iostream>
#include <vector>
#include <algorithm>
void Print (const int& i) {
std::cout << i << " ";
}
int main() {
std::vector<int> v{0, 1, 2, 3};
for (std::size_t x = 0; x < v.size(); ++x) {
std::cout << "[ ";
std::for_each (v.begin() + 1, v.end(), Print);
std::cout << "]" << std::endl;
std::swap (v[0], v[(x + 1) % v.size()]);
}
return 0;
}
Output:
[ 1 2 3 ]
[ 0 2 3 ]
[ 0 1 3 ]
[ 0 1 2 ]
While this could be done with a single function call, I like that it's a bit clearer what's happening when there are two functions.
The idea is that you need to not print a different element each time you print the vector. You need to print n
times, as stated, so loop n
times, excluding the element at index n
each time.
My use of the fmt
library is a personal convenience on this machine. Substitue whatever printing mechanism you're using.
#include <fmt/core.h>
#include <vector>
void print_excluding_one(std::vector<int> const& v, std::size_t exclude) {
fmt::print("[ ");
for (std::size_t idx = 0; idx < v.size(); ++idx) {
if (idx != exclude) {
fmt::print("{} ", v[idx]);
}
}
fmt::print("]\n");
}
void do_the_thing(std::vector<int> const& v) {
for (std::size_t idx = 0; idx < v.size(); ++idx) {
print_excluding_one(v, idx);
}
}
int main() {
std::vector<int> v{0, 1, 2, 3};
do_the_thing(v);
}
Output:
[ 1 2 3 ]
[ 0 2 3 ]
[ 0 1 3 ]
[ 0 1 2 ]
If you can use C++23, things can go as simple as this:
#include <span>
#include <array>
#include <print>
#include <ranges>
#include <format>
void my_print(std::span<int> arr){
using namespace std::views;
for (auto i:iota(0,size(arr)))
std::println( "{}"
, std::array
{ std::span(arr | take(i)
, std::span(arr | drop(i+1)) }
| join );
};
views::concat
would make it even simpler if available:
concat(arr | take(i), arr | drop(i+1))
That's simpler than array/span/join mombo-jumbo. In case C++23 is not an option or any of the above utilities are not available, turning std::println
into a pair of loops(one for view::take
, the other for views::drop
) is not that difficult.
Using <ranges>
extremely enhances readability; Back porting code to older platforms becomes trivial due to its readability.
Using C++23 with GCC 14.2, the ranges library and the FMT library:
#include <ranges>
#include <vector>
namespace rng = std::ranges;
namespace vws = std::views;
using vws::iota, vws::drop, vws::take;
#include <fmt/ranges.h>
using fmt::println, fmt::print;
auto main() -> int {
auto vec_orig = vws::iota(0, 4) | rng::to<std::vector>();
println("{}\n", vec_orig);
for (size_t n{0}; n < vec_orig.size(); ++n) {
auto vec = {
vec_orig | take(n) | rng::to<std::vector>(),
vec_orig | drop(n + 1) | rng::to<std::vector>()
};
println("{:}", rng::join_view(vec));
}
return 0;
}
Live code.
本文标签: cPrint n vectors of n1 elementsStack Overflow
版权声明:本文标题:c++ - Print n vectors of n-1 elements - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741797386a2398016.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论