繁体   English   中英

将CSV中的2D数组读取到Map c ++中

[英]Read 2D array in CSV into a Map c++

我是CPLEX用户,我需要将CSV文件中的数组数据转换为C ++ 2D Map作为优化问题的输入。 数据显示为列。 也就是说,如果我们考虑3行(AA1,AA2,AA3)和3列(BB1,BB2,BB3)及其各自的值,则它们在CSV文件中具有以下格式:

行,颜色,值
AA1,BB1、0.3
AA2,BB1、0.5
AA1,BB2、0.6
AA1,BB3、0.7
AA2,BB2、0.9
AA3,BB2、0.5
AA3,BB1、0.6
AA2,BB3、0.4
AA3,BB3、0.6

如您所见,数据既不按行也不按列排序。 我希望将数据读取为格式为“ map <字符串,map <字符串,float >> ”的2D Map,以便对生成的map进行排序:

行,颜色,值
AA1,BB1、0.3
AA1,BB2、0.6
AA1,BB3、0.7
AA2,BB1、0.5
AA2,BB2、0.9
AA2,BB3、0.4
AA3,BB1、0.6
AA3,BB2、0.5
AA3,BB3、0.6

任何帮助将不胜感激! 谢谢。

[编辑]行数和列数是预先已知的-无需计数。 我对C ++相对较新(从OPL优化语言迁移),并且对文件操作不是很熟悉。 任何示例代码都将对我理解该过程非常有帮助。

由于您将空格用作分隔字符,因此您应该能够使用标准的<ifstream>实现来相当快地实现此功能:

#include <ifstream>
#include <string>
#include <map>
#include <iostream>

int main() {
    // Open file:
    std::ifstream fin("filename.csv"); // Open in text-mode.

    // Opening may fail, always check.
    if (!fin) { 
        std::cout << "Error, could not open file." << std::endl; 
        return -1;
    }

    // Construct your map.
    std::map< std::string, std::map<std::sting, float> > valMap;

    // Read the file and load the data:
    std::string row, column;
    float value;
    while ( fin >> row >> column >> value ) { // Reads three values from file.
          valMap[row][col] = value;  // Adding the values to the map, if the cell is 
                                     // a duplicate: It will be overwritten.
    }

    // Close the file:
    fin.close();

    // Printing out the data like you described:
    for ( auto & columnMap : valMap ) {
        for ( auto cell : columnMap.second ) {
                std::cout << columnMap->first /*First label*/ << " "
                          << cell->first      /*Second label*/ << " "
                          << cell->second     /* Value */ << std::endl;
        }
    }

    return 0;
}

好的,我将在第二个答案中添加它,因为它是解决同一问题的完全不同的方法。

如果可以有许多不同的定界符,则strtok是一个很好的选择。 它最初是C,所以您需要多动一点手,但这是值得的。

char * strtok ( char * str, const char * delimiters );

有两个参数,第一个是我们要分析的字符串,第二个是包含我们要用作定界符的所有不同字符的字符串。

对于您特殊的用例,我将提出以下建议:

#include <cstring>
#include <cstdlib>
#include <string>
#include <fstream>
#include <iostream>

const char * DELIMS = "\t ,"; // Tab, space or comma.
const int MAX_LINE_LENGTH = 1024; // Choose this large enough for your need.
                                  // Or use a dynamic buffer together with 
                                  // std::string and getline(istream, string&).

int main() {
    std::fstream fin("filename.csv");

    // Test for errors

    // Prepare a C-string buffer to be used when reading lines.
    char buffer[MAX_LINE_LENGTH] = {};        

    // Prepare map.
    std::map< std::string, std::map< std::string, float>> valMap;

    // Read one line at a time.
    while ( fin.getline(buffer, MAX_LINE_LENGTH) ) {
          // Extract the three tokens:
          const char * row = strtok( buffer, DELIMS );
          const char * col = strtok( NULL,   DELIMS );
          const char * val = strtok( NULL,   DELIMS );

          // You could do additional errorchecking here, 
          // as for instance checking that there are no more valid tokens, 
          // and that all row, col and val are non-NULL.

          // Insert elements.
          valMap[std::string(row)][std::string(col)] = std::atof(val);
    }      

    // Cleanup
    fin.close();
}  

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM