簡體   English   中英

在 node.js 中將包含有序數據的兩個流合並為一個流

[英]Merge two streams containing ordered data into one stream in node.js

我是 node.js 的新手。 問題是從 2 個(或更多)已排序數據的流中讀取,並生成它們的“排序合並”。 例如:

Stream A: 1 5 6 8
Stream B: 2 3 4 7
========================
Result: 1 2 3 4 5 6 7 8

在 C++/Java/C# 中,這有一個非常明顯的解決方案,例如:

BufferedReader[] readers = new BufferedReader[2];
String[] lines = new String[2];
// fill lines with initial values from both readers
// ...
while (true) {
    int earliestIndex = -1;
    // ....
    // determine earliestIndex by looping over lines and comparing them
    if (earliestIndex < 0) break;
    String line = lines[earliestIndex];
    // do something with line
    System.out.println(line);
    // advance reader
    lines[earliestIndex] = readers[earliestIndex].readLine();
}

但在節點中,這似乎相當困難。 有任何想法嗎?

這是我最終想出的解決方案。 我正在使用node-line-reader 逐行讀取流(文件流,但這可以輕松更改):

var LineReader = require('node-line-reader').LineReader;

var files = ['c:\\temp\\1.txt', 'c:\\temp\\2.txt'];
var readers = [];
var lines = [];

var readWhile = function (done) {
    var earliestIndex = -1;
    var earliest = MAX_VALUE;
    for (i = 0; i < lines.length; i++) {
        var l = lines[i];
        var value = parseInt(l);
        if (value < earliest) {
            earliest = value;
            earliestIndex = i;
        }
    }
    if (earliestIndex < 0) {
        done();
        return;
    }
    var line = lines[earliestIndex];
    console.log('Read from ' + files[earliestIndex] + ': ' + line);
    readers[earliestIndex].nextLine(function (err, line) {
        if (err) throw err;
        lines[earliestIndex] = line;
        process.nextTick(function () {
            readWhile(done);
        });
    });
}

new Promise(function (success, error) {
   for (i = 0; i < files.length; i++) {
      var reader = new LineReader(files[i]);
      readers.push(reader);
      new Promise(function (success, failure) {
         reader.nextLine(function (err, line) {
            if (err) failure(err);
            lines.push(line);
            success();
         });
      }).then(function (data) {
         if (lines.length == files.length) success();
      });
   }
}).then(function (data) {
    return new Promise(function (success, failure) {
        readWhile(success);
    });
}).then(function() {
   console.log('All done');
}, function (err) {
   console.log('Error: ' + err);
});

您可以查看有哪些內容將通過管道傳輸到您的流中,然后將其拆開並將其通過管道傳輸到您感興趣的流中:

`

var PassThrough = require('stream').PassThrough;

var stream3 = new PassThrough();

// When a source stream is piped to us, undo that pipe, and save
// off the source stream piped into our internally managed streams.
stream3.on('pipe', function(source) {
  source.unpipe(this);
  this.transformStream = source.pipe(stream1).pipe(stream2);
});

// When we're piped to another stream, instead pipe our internal
// transform stream to that destination.
stream3.pipe = function(destination, options) {
  return this.transformStream.pipe(destination, options);
};

stdin.pipe(stream3).pipe(stdout);`

您可以將此功能提取到自己的可構造流類中:

     var util = require('util');
var PassThrough = require('stream').PassThrough;

var StreamCombiner = function() {
  this.streams = Array.prototype.slice.apply(arguments);

  this.on('pipe', function(source) {
    source.unpipe(this);
    for(i in this.streams) {
      source = source.pipe(this.streams[i]);
    }
    this.transformStream = source;
  });
};

util.inherits(StreamCombiner, PassThrough);

StreamCombiner.prototype.pipe = function(dest, options) {
  return this.transformStream.pipe(dest, options);
};

var stream3 = new StreamCombiner(stream1, stream2);
stdin.pipe(stream3).pipe(stdout);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM