对双精度二维向量进行排序

3
我有一份数据列表(4列),我想按照某一列进行排序。它是从文件中读取到一个二维向量中的。我使用了std::sort方法,并编写了比较函数。程序已经编译并运行,但当我打印前10个元素时,它并没有被排序,但肯定与添加到二维向量中的顺序不同。
以下是代码:
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>
#include <iomanip>

using namespace std;

typedef vector<double> Row;
typedef vector<Row> Matrix;

bool sortByFourthColumn(const Row& row1, const Row& row2){
    return (double) row1[3] < (double) row2[3];
}

int main(){
    std::ifstream infile;
    infile.open("Test8_Output.txt");

    double x,y,z,E;
    char line[200];
    int line_count=0; 

    ofstream outfile;
    outfile.open("WO_crp.txt");

    if (infile.is_open()){

        while (!infile.eof()){
            infile.getline(line,170);

            if (line[0] != '%'){
            outfile<<line<<"\n";         
            line_count++;
            }
            else{
            }
    }

    Matrix data(line_count,Row(4));

    outfile.close();

    std::ifstream myfile;
    myfile.open("WO_crp.txt");

    int i = 0;
    while(myfile >> x >> y >> z >> E){
        data[0][i] = x;
        data[1][i] = y;
        data[2][i] = z;
        data[3][i] = E;
        i++;
    }
    myfile.close();

    std::sort(data.begin(), data.end(), sortByFourthColumn);

    for (int u = 0; u <20; u++){
        cout << setprecision(5) << data[0][u] << "\t" << setprecision(5)<< data[1][u] << "\t" << setprecision(5)<< data[2][u] << "\t" << setprecision(5)<< data[3][u] << endl;
    }

    }
    else{
        cout << "Error: File is invalid.\n";

    }
    return(0);
}

编辑 - 输入文件的样例:
编辑 2 - 在 Matrix data(4,Row(line_count)); 中交换了 4line_count

% Model:              CDS_Test8.mph
% Version:            COMSOL 5.2.0.220
% Date:               Jul 13 2016, 14:33
% Dimension:          3
% Nodes:              86183
% Expressions:        1
% Description:        Electric field norm
% Length unit:        m
% x                       y                        z                        es.normE (V/m)
0.13774675805195374       0.05012986567931247      0.20735                  67.35120820901535
0.13870000000000005       0.04957489750396299      0.20735000000000003      102.8772500513651
0.13870000000000002       0.050800000000000005     0.20735                  87.56008679032011
0.13792733849817027       0.050131465727838186     0.20801419247484804      73.55192534768238
0.13674627634411463       0.04992349737428063      0.20735                  63.23018910026428
0.13750191177019236       0.0508                   0.20735000000000003      67.26176884022838
0.13827743496772454       0.05193409099097887      0.20734999999999998      73.35474409597487
0.13803618792088135       0.05134931748395268      0.20841988134890965      75.3712126982815
0.13905949760011943       0.05141879754884912      0.20734999999999998      83.70739713476813
0.13896970815034013       0.05092428105421264      0.208142746399683        84.73571510992372
0.1390220807917094        0.0501245422629353       0.20817502757007986      85.57119242707628
0.13944867847480893       0.05161480113017738      0.2081969878426443       89.65643851109644

接下来大约还有87000行左右的内容。


1
我有点困惑。难道 std::sort 不会处理排序(因此也包括交换)吗?为什么还需要一个 swap 函数? - Chami Sangeeth Amarasinghe
1
使用Matrix data(4,Row(line_count))声明了一个元素类型为Row(line_count)的4个元素的向量(一个包含line_count个双精度数的向量)。你应该在程序的其余部分中交换4和line_count等参数。 - Bob__
完成。以“%”开头的行不一定要去掉;但是我这样做是为了更容易填充向量。 - Chami Sangeeth Amarasinghe
C++11是一个选项吗? - Bob__
1
你在索引时仍然把维度反了。现在 line_count 是第一个索引,你的循环索引 iu 也必须是第一个索引。 - Peter
显示剩余4条评论
1个回答

2
我有一个包含4列数据的列表,我想按照某一列进行排序。
问题在于,在OP程序中用于存储数据的向量的维度在声明和使用时不一致。
一个小问题是使用了 while(!infile.eof()){...,这应该被避免。
修正后的版本如下:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <array>
#include <algorithm>
#include <iomanip>

using Row = std::array<double,4>;     // instead of typedefs
using Matrix = std::vector<Row>;
using std::cout;

bool sortByFourthColumn(const Row& row1, const Row& row2){
    return row1[3] < row2[3];
    //     ^  The cast is unnecessary
}

int main(){

    std::string file_name{"Test8_Output.txt"};
    std::ifstream infile{file_name, std::ios_base::in};
    if ( !infile ) {
        cout << "Error: unable to open file " << file_name << '\n';
        return EXIT_FAILURE;
    }

    Matrix data;
    data.reserve(90000);  // if you are afraid of the reallocations
    int count = 0;
    std::string line;

    // instead of two loops you can use one loop and read the file once
    // I'll use std::getline to extract a row in a std::string
    while ( std::getline(infile, line) ) {
        // skip comments and empty lines
        if ( line.empty() || line[0] == '%' )
            continue;
        ++count;

        // extract data from the string using a stringstream
        std::stringstream ss{line};
        Row r;
        ss >> r[0] >> r[1] >> r[2] >> r[3];
        if ( !ss ) {
            cout << "Format error in line " << count << " of file.\n";
            break;
        }
        data.push_back(std::move(r));
    }

    std::sort(data.begin(), data.end(), sortByFourthColumn);
    cout << std::setprecision(5) << std::fixed;

    for ( const auto & r : data ) {
        for ( auto const &x : r ) {
            cout << std::setw(10) << x;
        }
        cout << '\n';
    }
    return EXIT_SUCCESS;
}

输出结果,给定示例数据为:
   0.13675   0.04992   0.20735  63.23019
   0.13750   0.05080   0.20735  67.26177
   0.13775   0.05013   0.20735  67.35121
   0.13828   0.05193   0.20735  73.35474
   0.13793   0.05013   0.20801  73.55193
   0.13804   0.05135   0.20842  75.37121
   0.13906   0.05142   0.20735  83.70740
   0.13897   0.05092   0.20814  84.73572
   0.13902   0.05012   0.20818  85.57119
   0.13870   0.05080   0.20735  87.56009
   0.13945   0.05161   0.20820  89.65644
   0.13870   0.04957   0.20735 102.87725

感谢您指出关键错误,以及提供的建议。我已经使程序运行起来了。我将实施您版本中的大部分内容 - 它更加流畅。 - Chami Sangeeth Amarasinghe
@ChamiSangeethAmarasinghe 不用谢,很高兴能帮到您。 - Bob__

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接