【问题标题】:Grabbing a random line from file从文件中抓取随机行
【发布时间】:2012-11-03 17:31:49
【问题描述】:

我不知道该怎么做。我应该从哪里开始?我已经用谷歌搜索了这个,但没有一个关于如何从文本文件中提取随机行的结果。

我找到的唯一东西是https://github.com/chrisinajar/node-rand-line,但是它不起作用。如何从文本文件中读取随机行?

【问题讨论】:

  • 这个文件有多大?一种简单的方法是读取整个文件,然后随机选择一行。但是,这至少需要与文件一样多的内存。
  • 2MB?直接读入内存

标签: javascript node.js


【解决方案1】:

您可能希望查看用于读取文件的 node.js 标准库函数fs.readFile,并最终得到以下内容:

const fs = require("fs");
// note this will be async
function getRandomLine(filename, callback){
  fs.readFile(filename, "utf-8", function(err, data){
    if(err) {
        throw err;
    }

    // note: this assumes `data` is a string - you may need
    //       to coerce it - see the comments for an approach
    var lines = data.split('\n');
    
    // choose one of the lines...
    var line = lines[Math.floor(Math.random()*lines.length)]

    // invoke the callback with our line
    callback(line);
 })
}

如果阅读整篇文章和拆分不是一种选择,那么也许可以查看this stack overflow 的想法。

【讨论】:

  • 这对我不起作用,我得到了错误:data.split is not a function。根据this question 的答案,我添加了data+='',它起作用了。
  • 请注意,如果文件包含foo\nbar\n,该函数将返回'foo''bar''' 之一。修复例如通过将data.split('\n') 更改为data.replace(/\n$/, '').split('\n')
  • 您应该尝试返回行而不是在函数中执行某些操作
【解决方案2】:

我没有方便的 No​​de 来测试代码,所以我不能给你确切的代码,但我会做这样的事情:

  1. 以字节为单位获取文件大小,选择随机字节偏移量
  2. 以流形式打开文件
  3. 使用this snippet 来发射行(或readline,但我上次使用它有一个讨厌的错误,它基本上不起作用)
  4. 在阅读时跟踪您在文件中的位置。当您传递您选择的偏移量时,选择该行并返回它。

请注意,这并非完全随机。较长的行将被赋予更大的权重,但这是唯一无需读取整个文件即可获得行数的方法。

此方法允许您获取“随机”行,而无需将整个文件保存在内存中。

【讨论】:

  • 需要指出的是node.js这个OS特定的EOL标记可以通过os.EOL访问
【解决方案3】:

我可以给你一个建议,因为我没有任何演示代码

  1. 使用buffered reader逐行读取文件
  2. 将每一行存储在一个字符串数组中
  3. 创建方法int returnRandom(arraySize)
  4. 将数组大小传递给函数
  5. 计算0arraySize之间的随机数
  6. 返回随机数
  7. 从字符串数组中打印给定的索引

【讨论】:

    【解决方案4】:

    我有同样的需要从超过 100 个月的文件中随机选择一行。
    所以我想避免将所有文件内容存储在内存中。
    我最终对所有行进行了两次迭代:首先获取行数,然后获取目标行内容。
    下面是代码的样子:

    const readline = require('readline');
    const fs = require('fs');
    const FILE_PATH = 'data.ndjson';
    
    module.exports = async () =>
    {
        const linesCount = await getLinesCount();
        const randomLineIndex = Math.floor(Math.random() * linesCount);
        const content = await getLineContent(randomLineIndex);
        return content;
    };
    
    //
    // HELPERS
    //
    
    function getLineReader()
    {
        return readline.createInterface({
            input: fs.createReadStream(FILE_PATH)
        });
    }
    
    async function getLinesCount()
    {
        return new Promise(resolve =>
        {
            let counter = 0;
            getLineReader()
            .on('line', function (line)
            {
                counter++;
            })
            .on('close', () =>
            {
                resolve(counter);
            });
        });
    }
    
    async function getLineContent(index)
    {
        return new Promise(resolve =>
        {
            let counter = 0;
            getLineReader().on('line', function (line)
            {
                if (counter === index)
                {
                    resolve(line);
                }
                counter++;
            });
        });
    }
    

    【讨论】:

      猜你喜欢
      • 2017-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-26
      • 2015-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多