【问题标题】:Pick a random line from text file in C++从 C++ 中的文本文件中选择一个随机行
【发布时间】:2015-11-04 21:12:41
【问题描述】:

我正在尝试从文本文件中读取随机行。

到目前为止,我的代码选择了第一行,但我需要一个随机行。

如何获得随机线?

string line;
if(infile.good()){
    getline(infile, line);
}

【问题讨论】:

  • 什么是随机性?基于随机数生成器结果的任意行号?
  • 我掷了一个骰子,结果出现了一个 1。好像你的代码没问题。
  • 弄清楚如何获取特定 k 的第 k 行。添加随机性。
  • 获取一个随机数并将其存储在x。阅读x-1 行。那么你阅读的下一行将是你使用的那一行。

标签: c++ file random-sample


【解决方案1】:

您可以使用这些相关帖子中描述的“水库采样”方法:

正如我们从 Wikipedia 上关于水库采样的文章中了解到的:

水库抽样是一系列随机算法,用于从包含 n 个项目的列表 S 中随机选择 k 个项目的样本,其中 n 是一个非常大或未知的数字。通常 n 足够大,以至于列表不适合主内存。

使用这种算法,可以一次从一系列未知长度中挑选出随机元素,而无需将它们全部存储在内存中。

这是一个(未经测试的)示例:

#include <cstdlib>
#include <iostream>
#include <random>
#include <string>
int main() {
    std::random_device seed;
    std::mt19937 prng(seed());
    std::string line, result;
    for(std::size_t n = 0; std::getline(std::cin, line); n++) {
        std::uniform_int_distribution<> dist(0, n);
        if (dist(prng) < 1)
            result = line;
    }
    std::cout << "random line: '" << result << "'\n";
}

示例输出:

$ g++ test.cc -std=c++11 && ./a.out < test.cc
random line: '#include <iostream>'

供参考:

【讨论】:

    【解决方案2】:

    您可以将文件的行读入std::vector&lt;std::string&gt;随机访问向量大小范围内的特定行:

    std::string line;
    std::vector<std::string> lines;
    while(getline(infile, line)) {
        lines.push_back(line);
    }
    
    if(lines.size() >= 4) {
         std::cout << "Line number 5: " << lines[4] << std::endl;
    }
    

    另一种选择是先设置一个随机数,然后计算读取的行数:

    int lineno = 5;
    int linecount = 0;
    std::string line;
    while(getline(infile, line)) {
        ++linecount;
        if(linecount == lineno) {
            std::cout << "Line number " << lineno << ": " << line << std::endl;
        }
    }
    

    【讨论】:

    • 嗯,第一个会得到一个特定的行,它不会得到一个随机的。
    • @Solarmo 您可以将lineno 设置为随机数。
    【解决方案3】:

    随机调用getline 并确保在到达文件末尾时停止循环。

    只要您不知道文件中的行有多长,就无法以某种方式计算任何行的开头(当然第一行除外)并直接查找该点。

    【讨论】:

      【解决方案4】:

      您可以将行开头的文件偏移量存储到std::vector 中。接下来,生成您的随机数。使用该数字作为std::vector 的索引,并获取该行的起始位置。寻找那个位置并取线。

      std::vector<std::streampos> line_offsets;
      line_offsets.push_back(0); // The first line.
      std::string text_line;
      while (getline(text_file, text_line))
      {
        std::streampos file_offset = text_file.tellg();
        line_offsets.push_back(file_offset);
      }
      //...
      std::streampos offset = line_offsets[Get_Random_Line_Number()];
      text_file.seekg(offset);
      std::string random_text_line;
      getline(text_file, random_text_line);
      

      这种方法使用的内存不如将每个文本行存储到一个向量中。

      【讨论】:

      • 什么是 Get_Random_Line_Number() ??
      • 这是一个你写的函数来返回一个随机的行号。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-10
      • 2012-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-03
      相关资源
      最近更新 更多