如何在嵌套循环中匹配来自两个字符串向量的字符串值

Posted

技术标签:

【中文标题】如何在嵌套循环中匹配来自两个字符串向量的字符串值【英文标题】:How to match string values from two string vectors within a nested loop 【发布时间】:2013-11-22 06:50:01 【问题描述】:

我正在尝试在 CSV 文件中查找某些标头值的索引,以便我可以使用它们来提取文件其余部分中这些位置的数据。我将标头值添加到 map<std::string, int> 中,以便保留索引。

我有工作代码,直到我注意到如果标题是行中的最后一个值,它不匹配。最后一个标题字符串在我的嵌套循环中是空的,但在外循环中不是。

const int columnCount = 2;
std::string columns[columnCount] =  "column1", "column2" ;

map<std::string, int> columnMap;

std::vector<std::string> cols(columns, columns + columnCount);
std::vector<std::string> cells;

boost::tokenizer<boost::escaped_list_separator<char> > tok(header_row);
cells.assign(tok.begin(), tok.end());

std::vector<std::string>::iterator iter_cells;
std::vector<std::string>::iterator iter_cols;

for (iter_cells = cells.begin(); iter_cells != cells.end(); ++iter_cells) 
    std::string cell = *iter_cells; 
    for(iter_cols = cols.begin(); iter_cols != cols.end(); ++iter_cols) 
        std::string col = *iter_cols;
        cout << cell << "=" << col;
        if(col.compare(cell) == 0) 
            cout << " MATCH" << endl;
            columnMap.insert(std::make_pair(*iter_cols,iter_cells-cells.begin()));
            break;
        
        cout << endl;
    

tok(row) 相当于 tok("column0,column1,column2") 我得到这个输出;

column0=column1
column0=column2
column1=column1 MATCH
=column1
=column2

如果是 tok("column0,column1,column2,column3") 我明白了;

column0=column1
column0=column2
column1=column1 MATCH
column2=column1
column2=column2 MATCH
=column1
=column2

当我在外循环中cout &lt;&lt; cell 时,值显示正确。

为什么我在内部循环中丢失了cell 的值?

编辑

Code in github 和测试文件编译用;

gcc parse_csv.cpp -o parse_csv -lboost_filesystem -lmysqlpp

并用

执行
./parse_csv /home/dave/SO_Q/

我得到这个输出;

Process File: /home/dave/SO_Q/test_2.csv
metTime
metTime=metTime MATCH
Ta
=metTime
=Ta
=Ua
=Th
Process File: /home/dave/SO_Q/test_1.csv
DATE_TIME_UTC
DATE_TIME_UTC=metTime
DATE_TIME_UTC=Ta
DATE_TIME_UTC=Ua
DATE_TIME_UTC=Th
Ta
Ta=metTime
Ta=Ta MATCH
metTime
=metTime
=TaTime
=UaTime
=ThTime

【问题讨论】:

正如 Nik 所演示的,这段代码应该可以工作。我也看不出有什么问题。所以问题出在你的问题中缺少的东西。你认为你可以发布一个有这个问题的完整程序吗,最好尽可能小。 @john,谢谢,我想我已经添加了更完整的代码版本和我在这里使用的两个测试文件; github.com/davecanderson/***_20138787 【参考方案1】:

不确定你是如何填充变量“header_row”的,但下面的代码对我有用,我得到了这个输出

column0=column1

column0=column2

column1=column1 匹配

column2=column1

column2=column2 匹配

column3=column1

column3=column2

#include  <boost/tokenizer.hpp>
#include <iostream>
#include <fstream>
#include <map>

using namespace std;



int main()

  //create csv
  ofstream csvFile ("data.csv");
  std::string row = "column0,column1,column2,column3";

  csvFile << row;

  csvFile.close();

  const int columnCount = 2;
  std::string columns[columnCount] =  "column1", "column2" ;

  map<std::string, int> columnMap;

  std::vector<std::string> cols(columns, columns + columnCount);
  std::vector<std::string> cells;

  //open csv file
  std::string header_row;
  ifstream csvRead("data.csv");
  assert(csvRead.is_open());
  getline(csvRead,header_row);

  boost::tokenizer<boost::escaped_list_separator<char> > tok(header_row);
  cells.assign(tok.begin(), tok.end());
  //close file
  csvRead.close();

  std::vector<std::string>::iterator iter_cells;
  std::vector<std::string>::iterator iter_cols;
  
 //original loops as provided in question
  for (iter_cells = cells.begin(); iter_cells != cells.end(); ++iter_cells) 
    std::string cell = *iter_cells;
    for(iter_cols = cols.begin(); iter_cols != cols.end(); ++iter_cols) 
      std::string col = *iter_cols;
      cout << cell << "=" << col;
      if(col.compare(cell) == 0) 
        cout << " MATCH" << endl;
        columnMap.insert(std::make_pair(*iter_cols,iter_cells-cells.begin()));
        break;
      
      cout << endl;
    
  


【讨论】:

这不是一个真正的答案,它应该是一个评论。您还没有解释为什么 OP 的代码不起作用。 @john 点了。循环的运行方式没有问题。问题可能在于如何填充“header_row”。 谢谢@Nik,标题通过使用std::string header_row; std::ifstream data(filename.c_str()); std::getline(data, header_row);读取CSV文件的第一行进入我已经将URL发布到问题cmets中的github存储库中,其中包含一些测试数据和代码我有。【参考方案2】:

问题在于标题行的输入。这在末尾包含一个与数组中的项目不匹配的换行符。删除换行符解决了问题。

我在 Windows PC 上工作,然后将文件传输到 Cent OS 机器以运行代码,两个平台之间行尾的差异是导致问题的原因。

将其用作调试语句cout &lt;&lt; cell 将显示字符串并忽略换行符。由于换行,使用类似cout &lt;&lt; cell &lt;&lt; " CELL" 的东西没有显示字符串。

我现在在我的代码中添加了这个来捕捉换行符的差异

// remove possible windows line ending so last item matches
if(header_row[header_row.length()-1] == '\r') 
    header_row.erase(header_row.size()-1);

【讨论】:

以上是关于如何在嵌套循环中匹配来自两个字符串向量的字符串值的主要内容,如果未能解决你的问题,请参考以下文章

如何在嵌套的 for 循环中使用 continue 语句之类的东西?

Pandas 使用 for 循环在部分字符串匹配上设置列:使用包含 NaN 的向量进行错误索引

Java初学者,比较嵌套for循环中的字符串

如何执行嵌套 Thymeleaf 循环以创建包含来自两个 JPA 表类的字段的表

如何在与用户给定前缀匹配的字符串向量中找到第一个单词?

在 cython 的循环中创建 c++ 映射