【问题标题】:Is it possible for this code to lose some matches?此代码是否有可能丢失一些匹配项?
【发布时间】:2015-06-28 12:58:47
【问题描述】:

在我学习 NodeJS 的过程中,我在一本书(NodeJS in Practice)中找到了这个示例代码,它使用流来查找来自另一个流的数据中的一些匹配项。

var Writable = require('stream').Writable;
var util = require('util');
module.exports = CountStream;
util.inherits(CountStream, Writable);

function CountStream(matchText, options) {
    Writable.call(this, options);
    this.count = 0;
    this.matcher = new RegExp(matchText, 'ig');
}

CountStream.prototype._write = function(chunk, encoding, cb) {
    var matches = chunk.toString().match(this.matcher);
    if (matches) {
        this.count += matches.length;
    }
    cb();
};

CountStream.prototype.end = function() {
    this.emit('total', this.count);
};

以及使用流的代码:

var CountStream = require('./countstream');
var countStream = new CountStream('book');
var http = require('http');

http.get('http://www.manning.com', function(res) {
    res.pipe(countStream);
});

countStream.on('total', function(count) {
    console.log('Total matches:', count);
});

如果匹配在两个数据块中中断,是否有可能丢失一些匹配?

例如第一个数据块包含 'This a bo',另一个数据块包含 'ok of mine。' 没有人没有 book 独立,但整个数据包含一本书

找到所有匹配项的最佳解决方案是什么?

【问题讨论】:

  • 很好看。是的,我会说它可以松散比赛。可能不会经常发生,因为我猜块会很大,这会使错误间歇性 - 最糟糕的错误。
  • 确实如此。此外,如果模式大小大于块大小(对于大多数用例而言,这通常不是什么大问题)。避免这种情况的一种方法(如果您只需要查找子字符串匹配项)是使用KMP 或任何其他可以以基于流的方式工作的算法。 @James:打败我!我是一个打字慢的人。叹息。
  • 你真的需要正则表达式,还是在寻找简单的匹配?
  • @Bergi 我认为搜索正则表达式更具挑战性。不使用正则表达式会更容易,因为搜索字符串的长度是可预测的?
  • @Bergi 同意。我认为在这种情况下,只匹配字符串的答案就足够了。

标签: javascript node.js


【解决方案1】:

所以,就像我在 cmets 中解释的那样,如果您知道与您的正则表达式匹配的字符串的最大长度(要计算最大长度,请参阅 https://stackoverflow.com/a/31173778/4114922 的非常好的答案),您可以缓存前一个块并连接它到新的块。 使用这种方法,我认为您不会输掉任何比赛。

var Writable = require('stream').Writable;
var util = require('util');
module.exports = CountStream;
util.inherits(CountStream, Writable);

function CountStream(matchText, maxPatternLength, options) {
    Writable.call(this, options);
    this.count = 0;
    this.matcher = new RegExp(matchText, 'ig');

    this.previousCache = undefined;
    this.maxPatternLength = maxPatternLength;
}

CountStream.prototype._write = function(chunk, encoding, cb) {
    var text;
    if(this.previousCache === undefined) {
        text = chunk.toString();
    }
    else {
        text = this.previousCache + chunk.toString();
    }
    var matches = text.match(this.matcher);
    if (matches) {
        this.count += matches.length;
    }

    this.previousCache = text.substring(text.length - this.maxPatternLength);

    cb();
};

CountStream.prototype.end = function() {
    this.emit('total', this.count);
};

【讨论】:

    猜你喜欢
    • 2011-06-25
    • 2023-03-09
    • 2016-03-13
    • 2014-01-17
    • 1970-01-01
    • 1970-01-01
    • 2016-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多