RxJs - parse file, group lines by topics, but I miss the end

我怕爱的太早我们不能终老 提交于 2019-12-12 03:25:03

问题


I am trying RxJS.

My use case is to parse a log file and group lines by topic ( i.e.: the beginning of the group is the filename and then after that I have some lines with user, date/time and so on) I can analyse the lines using regExp. I can determine the beginning of the group.

I use ".scan" to group the lines together, when I've the beginning of new group of line, I create an observer on the lines I've accumulated ... fine.

The issue is the end of the file. I've started a new group, I am accumulating lines but I can not trigger the last sequence as I do not have the information that the end. I would have expect to have the information in the complete (but not)

Here is an example using number. Begin of group can multi of 3 or 5. (remark: I work in typescript)

import * as Rx from "rx";

let r = Rx.Observable
        .range(0, 8)
        .scan( function(acc: number[], value: number): number[]{
            if (( value % 3 === 0) || ( value % 5 === 0)) {
                acc.push(value);
                let info = acc.join(".");
                Rx.Observable
                    .fromArray(acc)
                    .subscribe( (value) => {
                        console.log(info, "=>", value);
                    });
                acc = [];
            } else {
                acc.push(value);
            }
            return acc;
        }, [])
        .subscribe( function (x) {
            // console.log(x);
        });  

This emit:

 0 => 0
 1.2.3 => 1
 1.2.3 => 2
 1.2.3 => 3
 4.5 => 4
 4.5 => 5
 6 => 6

I am looking how to emit

 0 => 0
 1.2.3 => 1
 1.2.3 => 2
 1.2.3 => 3
 4.5 => 4
 4.5 => 5
 6 => 6
 7.8 => 7     last items are missing as I do not know how to detect end
 7.8 => 8        

Can you help me, grouping items? Any good idea, even not using scan, is welcome.

Thank in advance


回答1:


You can use the materialize operator. See the documentation here and the marbles here, and an example of use from SO.

In your case, I would try something like (untested but hopefully you can complete it yourself, note that I don't know a thing about typescript so there might be some syntax errors):

import * as Rx from "rx";

let r = Rx.Observable
        .range(0, 8)
        .materialize()
        .scan( function(acc: number[], materializedNumber: Rx.Notification<number>): number[]{
            let rangeValue: number = materializedNumber.value;

            if (( rangeValue % 3 === 0) || ( rangeValue % 5 === 0)) {
                acc.push(rangeValue);
                generateNewObserverOnGroupOf(acc);
                acc = [];
            } else if ( materializedNumber.kind === "C") {
                generateNewObserverOnGroupOf(acc);
                acc = [];
            } else {
                acc.push(rangeValue);
            }
            return acc;
        }, [])
        // .dematerialize()
        .subscribe( function (x) {
            // console.log(x);
        });

function generateNewObserverOnGroupOf(acc: number[]) {
    let info = acc.join(".");
                Rx.Observable
                    .fromArray(acc)
                    .subscribe( (value) => {
                        console.log(info, "=>", value);
                    });

The idea is that the materialize and dematerialize works with notifications, which encodes whether the message being passed by the stream is one of next, error, completed kinds (respectively 'N', 'E', 'C' values for the kind property). If you have a next notification, then the value passed is in the value field of the notification object. Note that you need to dematerialize to return to the normal behaviour of the stream so it can complete and free resources when finished.



来源:https://stackoverflow.com/questions/36295133/rxjs-parse-file-group-lines-by-topics-but-i-miss-the-end

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!