Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/424.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在RxJs中连接两个半_Javascript_Rxjs_Rxjs5 - Fatal编程技术网

Javascript 如何在RxJs中连接两个半

Javascript 如何在RxJs中连接两个半,javascript,rxjs,rxjs5,Javascript,Rxjs,Rxjs5,我有一条像这样的小溪 ---ab---ab---a---ba---bab---ab---ab---ab---> 我想要这个 ---ab---ab------ab----ab-ab-ab---ab---ab---> 关键是,我有带开始和结束(JSON)的数据,有时数据在流中被切成两半,我想再次加入它们。我该怎么做呢?看起来像是扫描操作员的工作 // substitute appropriate real-world logic const isProperlyFormed = (x

我有一条像这样的小溪

---ab---ab---a---ba---bab---ab---ab---ab--->
我想要这个

---ab---ab------ab----ab-ab-ab---ab---ab--->

关键是,我有带开始和结束(JSON)的数据,有时数据在流中被切成两半,我想再次加入它们。我该怎么做呢?

看起来像是扫描操作员的工作

// substitute appropriate real-world logic
const isProperlyFormed = (x) => x === 'ab'  
const isIncomplete = (x) => x[0] === 'a' && x.length === 1
const startsWithEnding = (x) => x[0] === 'b'
const getCorrected = (buffer, x) => buffer.prev + x[0]
const getTail = (buffer, x) => x.slice(1)

const initialBuffer = {
  emit: [],
  prev: null
}

const result = source
  .scan((buffer, x) => {
    if (isProperlyFormed(x)) {
      buffer = {emit: [x], prev:null}
    }
    if (isIncomplete(x)) {
      buffer = {emit: [], prev:x}
    }
    if (startsWithEnding(x)) {
      const corrected = getCorrected(buffer, x)
      const tail = getTail(buffer, x)
      if (isProperlyFormed(tail)) {
        buffer = {emit: [corrected, tail], prev: null}
      } else {
        buffer = {emit: [corrected], prev: tail}
      }
    }
    return buffer
  }, initialBuffer)
  .flatMap(x => x.emit)
工作

编辑

查看测试输入流,我认为缺少了一个案例,这将打破上述情况

我把考试改为

---ab---ab---a---ba---bab---ab---ab---ab--->

并且简化了算法

const getNextBuffer = (x) => {
  const items = x.split(/(ab)/g).filter(y => y)  // get valid items plus tail
  return {
    emit: items.filter(x => x === 'ab'),    // emit valid items
    save: items.filter(x => x !== 'ab')[0]  // save tail
  }
}

const initialBuffer = {
  emit: [],
  save: null
}

const result = source
  .scan((buffer, item) => {
    const bufferAndItem = (buffer.save ? buffer.save : '') + item
    return getNextBuffer(bufferAndItem)
  }, initialBuffer)
  .flatMap(x => x.emit)

工作示例首先将流拆分为完整响应和部分响应。然后检查响应是否已满。完整的回答本身就是好的。部分响应需要同步,所以我们将它们的流分为第一部分和第二部分,然后将这些流压缩在一起

(g.partition(x=>x[0]=='a'))的奇怪外观是因为
partition
操作符返回一对无法链接的可观察对象

const testStream=Rx.Observable.of('a1','a2','u ab','b1','a3','b2','u ab','a4','b3','u ab','b4','a5','b5','u ab'))
测试流
.groupBy(x=>(x[0]==''&&&'full')| |'partial'))
.mergeMap(g=>
Rx.Observable.if(
()=>g.key=='full',
G
可观测的(g.分区(x=>x[0]='a'))
.mergeMap(([as,bs])=>Rx.Observable.zip(as,bs))
)
)
.do(x=>console.log(x))
.subscribe()
我就是这样解决的:

import Rx from 'rxjs/Rx';
import {last} from 'lodash';

const data$ = Rx.Observable.of('ab','ab','a','ba','bab','aba','b','ab');
const line$ = data$.flatMap(data => {
    const lines = data.match(/[^b]+b?|b/g); // https://stackoverflow.com/a/36465144/598280 https://stackoverflow.com/a/25221523/598280
    return Rx.Observable.from(lines);
});

const isComplete$ = line$.scan((acc, value) => {
    const isLineEndingLast = last(acc.value) === 'b';
    const id = isLineEndingLast ? acc.id + 1 : acc.id;
    const complete = last(value) === 'b';
    return {value, id, complete};
}, {value: 'b', id: 0, complete: true});

const grouped$ = isComplete$
    .groupBy(data => data.id, data => data, group => group.first(data => data.complete))
    .flatMap(group => group.reduce((acc, data) => acc + data.value, ''));

grouped$.subscribe(console.log);

但是如何区分
ab
a
?我在想,但我肯定那不是正确的事情。
import Rx from 'rxjs/Rx';
import {last} from 'lodash';

const data$ = Rx.Observable.of('ab','ab','a','ba','bab','aba','b','ab');
const line$ = data$.flatMap(data => {
    const lines = data.match(/[^b]+b?|b/g); // https://stackoverflow.com/a/36465144/598280 https://stackoverflow.com/a/25221523/598280
    return Rx.Observable.from(lines);
});

const isComplete$ = line$.scan((acc, value) => {
    const isLineEndingLast = last(acc.value) === 'b';
    const id = isLineEndingLast ? acc.id + 1 : acc.id;
    const complete = last(value) === 'b';
    return {value, id, complete};
}, {value: 'b', id: 0, complete: true});

const grouped$ = isComplete$
    .groupBy(data => data.id, data => data, group => group.first(data => data.complete))
    .flatMap(group => group.reduce((acc, data) => acc + data.value, ''));

grouped$.subscribe(console.log);