简体   繁体   English

以列表为值将文件读入 map

[英]reading a file into map with list as value

I have a file where each row is separated by a '|'我有一个文件,其中每一行都用“|”分隔delimiter eg:分隔符例如:

1|23|1234|car|10
2|12|345|taxi|11

where each first value is unique.其中每个第一个值都是唯一的。 I want to read it into a map so that first value is the key and the following ones are a list of values for that key.我想将它读入 map 以便第一个值是键,以下是该键的值列表。

I have the following implementation, but I'm not sure if my way of locating the delimiter is correct or how to assign the needed value as key.我有以下实现,但我不确定我定位分隔符的方式是否正确或如何将所需的值分配为键。

   std::map<int, list<>> sample_map;
   
   

   std::ifstream in("file.txt");
   unsigned sum = 0;
   string line;
   while (getline(in, line)) {
      const char *last = nullptr;
      unsigned col = 0;
      for (char &c : line)
         if (c == '|') {
            ++col;
            if (col == 1) {
               unsigned v;
               from_chars(last, &c, v);
               // assign v to key and rest of the data 
               // as values (excluding delimiter) 
               
               break;
            }
         }
   }


I highly recommend using a struct or class to model the input row (record):我强烈建议使用structclassmodel输入行(记录):

struct Record  
{  
    int id;
    int column2;
    int column3;  
    int name;  
    int last_column;
    // Overload operator >> for this record.
    friend std::istream& operator>>(std::istream& input, Record& r);
};

std::istream& operator>>(std::istream& input, Record& r)
{
    char separator;  
    input >> r.id;
    input >> separator;
    input >> r.column2; input >> separator;
    input >> r.column3; input >> separator;
    std::getline(input, r.name, '|');
    input >> r.last_column;
    input.ignore(100000, '\n'); // Reset to next line.  
    return input;
}

Your input code could look like this:您的输入代码可能如下所示:

std::map<int, Record> database;
Record r;
int id;
while (in >> r)
{
  id = r.id;
  database[id] = r;
}

There is a duplication of the ID in this implementation, but it uses the ID field as a key and you have your ID field in the record if you need it.在这个实现中有一个重复的 ID,但它使用 ID 字段作为键,如果需要,您可以在记录中使用 ID 字段。

I suggest adding a struct to keep the data and to overload operator>> to help with the input.我建议添加一个struct来保留数据并重载operator>>以帮助输入。 I've also added a mini-struct to eat up the delimiters |我还添加了一个迷你结构来吃掉分隔符| and \n - which could be done purely with std::getline but you'd then need to convert the integers so I decided to use the existing operator>> to read integers from the stream.\n - 这可以纯粹用std::getline完成,但你需要转换整数,所以我决定使用现有的operator>>从 stream 读取整数。

Example:例子:

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

//---------------------------------- a class to eat a delimiter
struct eat { char ch; };

// eat the expected character or set the stream in a failed state:
std::istream& operator>>(std::istream& is, const eat& e) {
    if(is.peek() == e.ch) is.ignore();
    else is.setstate(std::ios::failbit);
    return is;
}
//----------------------------------

struct data {    // the data the key in your map will map to
    unsigned a;
    unsigned b;
    std::string c;
    unsigned d;
};

// read one `data` from the stream:
std::istream& operator>>(std::istream& is, data& d) {
    eat e{'|'}; // used to eat up `|`
    return std::getline(is >> d.a >> e >> d.b >> e, d.c, '|') >> d.d >> eat{'\n'};
}

// print one `data`
std::ostream& operator<<(std::ostream& os, const data& d) {
    return os << d.a << '|' << d.b << '|' << d.c << '|' << d.d << '\n';
}

Reading the map from the file and printing it:从文件中读取 map 并打印:

#include <fstream>

int main() {
    if(std::ifstream in("file.txt"); in) {

        std::map<int, data> m;

        int key;
        data d;

        // read one key and one `data` until that fails:
        while(in >> key >> eat{'|'} >> d) {
            m[key] = std::move(d);          // put it in the map
        }

        // print the result:
        for(auto&[k, v] : m) {
            std::cout << k << '|' << v;
        }
    }
}

Demo演示

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

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