【问题标题】:Writing a Boost ublas matrix to a text file将 Boost ublas 矩阵写入文本文件
【发布时间】:2015-06-01 05:43:31
【问题描述】:

我有一个 Boost ublas 矩阵,我想将它的内容打印到一个文本文件中。我有以下实现,它可以工作。

#include <iostream>
using namespace std;
#include "boost\numeric\ublas\matrix.hpp"
typedef boost::numeric::ublas::matrix<float> matrix;
#include <algorithm>
#include <iterator>
#include <fstream>

int main()
{
    fill(m1.begin2(), m1.begin2() + 400 * 500, 3.3);

    ofstream dat("file.txt");
    for (auto i = 0; i < 400 ; i++) {
        for (auto j = 0; j < 500; j++) {
            dat << m1(i, j) << "\t"; // Must seperate with Tab
        }
        dat << endl; // Must write on New line
    }

我想在不使用嵌套 for 循环的情况下编写此代码。我尝试了 ostreambuf_iterator API 如下

copy(m1.begin2(), m1.begin2() + 500 * 400, ostream_iterator<float>(dat, "\n")); // Can only new line everything

但是,如您所见,连续的元素是在新行上编写的,我无法像嵌套 for 循环那样实现排序类型。有没有办法做我在嵌套中使用 STL 算法所做的事情?

【问题讨论】:

    标签: c++ c++11 boost stl boost-ublas


    【解决方案1】:

    我喜欢 Boost Spirit Karma 来完成这些小型格式化/生成器任务。

    直接接近

    如果您不介意每行都有尾随制表符,这里是

    Live On Coliru

    matrix m1(4, 5);
    std::fill(m1.data().begin(), m1.data().end(), 1);
    
    using namespace boost::spirit::karma;
    std::ofstream("file.txt") << format_delimited(columns(m1.size2()) [auto_], '\t', m1.data()) << "\n";
    

    打印

    1.0 → 1.0 → 1.0 → 1.0 → 1.0 → 
    1.0 → 1.0 → 1.0 → 1.0 → 1.0 → 
    1.0 → 1.0 → 1.0 → 1.0 → 1.0 → 
    1.0 → 1.0 → 1.0 → 1.0 → 1.0 → 
    

    使用multi_array 视图

    当您将const_multi_array_ref 适配器用作原始存储的“视图”时,您将获得更大的灵活性:

    Live On Coliru

    std::ofstream("file.txt") << format(auto_ % '\t' % eol, 
         boost::const_multi_array_ref<float, 2>(&*m1.data().begin(), boost::extents[4][5]));
    

    结果相同,但每行没有尾随制表符:

    1.0 → 1.0 → 1.0 → 1.0 → 1.0
    1.0 → 1.0 → 1.0 → 1.0 → 1.0
    1.0 → 1.0 → 1.0 → 1.0 → 1.0
    1.0 → 1.0 → 1.0 → 1.0 → 1.0
    

    更新使用辅助函数使其更具可读性且不易出错:

    template <typename T> boost::const_multi_array_ref<T, 2> make_view(boost::numeric::ublas::matrix<T> const& m) {
        return  boost::const_multi_array_ref<T,2> (
                &*m.data().begin(),
                boost::extents[m.size1()][m.size2()]
            );
    }
    

    所以就变成了

    Live On Coliru

    std::cout << format(auto_ % '\t' % eol, make_view(m1)) << "\n";
    

    在我看来,非常优雅

    注意当然这些假设是行优先布局。

    【讨论】:

    • @Golazo 谢谢 :) 作为奖励,我刚刚添加了一个帮助程序 make_view 函数,该函数使其易于重用且阅读起来非常优雅:Live On Coliru
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多