2個R開頭的庫,都是函數式編程,對比學習能夠達到知識相互鞏固的目的!並且這兩個庫都很強大,都很經常使用!僅對比ArrayLike相關操做編程
pipe能夠組合一些特定的操做,以便複用數組
// 功能從一個流中取第n個開始後m個數據
import { pipe, from } from 'rxjs';
import { skip, take } from 'rxjs/operators';
const takeNM = (n: number, m: number) => pipe(skip(n), take(m));
from([1, 2, 3, 4, 5, 6, 7, 8, 9]).pipe(
takeNM(3, 6)
).subscribe(res => {
// 4,5,6,7,8,9
console.log(res)
});
複製代碼
import { zip as rzip, zipWith, zipObj } from 'ramda';
import { from, zip } from 'rxjs';
import { map } from 'rxjs/operators';
const ages = [27, 25, 29, 30];
const names = ['Foo', 'Bar', 'Beer'];
const isDev = [true, true, false, false];
/** * [ [ 27, 'Foo' ], [ 25, 'Bar' ], [ 29, 'Beer' ] ] */
console.log(rzip(ages)(names));
/** * [ { '27': 'Foo' }, { '25': 'Bar' }, { '29': 'Beer' } ] */
console.log(zipWith(
(x, y) => ({
[`${x}`]: y
})
)(ages, names));
/** * { Foo: 27, Bar: 25, Beer: 29 } */
console.log(zipObj(names)(ages));
zip(
from(ages),
from(names),
from(isDev)
).pipe(
map(([age, name, isDev]) => ({ age, name, isDev }))
).subscribe(res => {
/** * { age: 27, name: 'Foo', isDev: true } * { age: 25, name: 'Bar', isDev: true } * { age: 29, name: 'Beer', isDev: false } */
console.log(res)
})
// ramda 中的zip能夠操做2個成對數組
// 一樣功能能夠用zip和map組合操做符實現
// rxjs更靈活
複製代碼
import { xprod } from 'ramda';
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
/** [ [ 1, 4 ], [ 1, 5 ], [ 1, 6 ], [ 2, 4 ], [ 2, 5 ], [ 2, 6 ], [ 3, 4 ], [ 3, 5 ], [ 3, 6 ] ] */
console.log(xprod(arr1)(arr2));
import { from } from 'rxjs';
import { concatMap, map } from 'rxjs/operators';
// 時間維度
from(arr1).pipe(
mergeMap((x) => from(arr2).pipe(
map(item => [x, item])
))
).subscribe(res => console.log(res));
// 有序,依次,
from(arr1).pipe(
concatMap((x) => from(arr2).pipe(
map(item => [x, item])
))
).subscribe(res => {
/** [ 1, 4 ] [ 1, 5 ] [ 1, 6 ] [ 2, 4 ] [ 2, 5 ] [ 2, 6 ] [ 3, 4 ] [ 3, 5 ] [ 3, 6 ] */
console.log(res)
})
// mergeMap更合適,concatMap需等待complete
複製代碼
import { without as rwithout } from 'ramda';
const list1 = [1, 2];
const list2 = [1, 2, 1, 3, 4];
// [ 3, 4 ]
console.log(rwithout(list1)(list2))
import { from } from 'rxjs';
import { without } from '../operators/without';
from(list2).pipe(
without(
from(list1)
)
).subscribe(res => {
/**
* 3
* 4
*/
console.log(res)
})
rxjs沒有相似功能操做符,須要實現一個,需求:
假設有兩個流,從一個流中挑選出在第二流裏沒有出現過的值!
複製代碼
without實現,整體也比較簡單bash
import { OperatorFunction, Observable, Operator, Subscriber, ObservableInput, merge } from 'rxjs';
import { mergeAll } from 'rxjs/operators';
export function without<T, R>(...observables: ObservableInput<any>[]): OperatorFunction<T, R> {
return (source: Observable<T>) => source.lift(new WithoutOperator(...observables));
}
class WithoutOperator<T, R> implements Operator<T, R> {
private observables: ObservableInput<any>[]
constructor(...observables: ObservableInput<any>[]) {
this.observables = observables;
}
call(subscriber: Subscriber<R>, source: any): any {
return source.subscribe(new WithoutSubscriber(subscriber, this.observables));
}
}
class WithoutSubscriber<T, R> extends Subscriber<T> {
private old: Set<any> = new Set();
constructor(destination: Subscriber<R>, ...observables: ObservableInput<any>[]) {
super(destination);
merge(...observables).pipe(
mergeAll()
).subscribe(res => {
this.old.add(res);
});
}
protected _next(x: T) {
if (!this.old.has(x)) {
this.destination.next(x);
}
}
}
複製代碼
ramda(when) vs rxjs(zip,map)函數式編程