美文网首页
小工具iterate学习(加快类数组的遍历速度)

小工具iterate学习(加快类数组的遍历速度)

作者: Gary嘉骏 | 来源:发表于2018-08-13 10:14 被阅读0次

    github地址

    • 这是一个能在MapSet使用数组方法(如:map()filter(), reduce())。

    • 而且如果使用多个操作符时,能只迭代一次,而不是补个操作符迭代一次。大大加快运行速度,对于运行一个很大的Set会有明显的效果。

    这个包应用了ES6的Iterator的概念。默认可遍历的数据结构是具有Symbol.iterator的属性。通过运行next方法就可以获得如下对象

    {value:值, done: 是否到最后};
    

    包用法:

    iterate(uris)
      .filter(uri => uri.startsWith('file://'))
      .map(uri => uri.substr('file:///'.length))
      .toSet()
    

    简单说,toSet()之前都是在不停装饰实例,成为一个新的遍历器。之后才开始迭代。

    iterate(uris)
    

    上面逻辑是:

    function iterate<T>(collection: Iterator<T> | Iterable<T>): IteratorWithOperators<T> {
        return new IteratorWithOperators(toIterator(collection))
    }
    

    就是用被传入对象的遍历器生成一个新的可遍历对象。

    export class IteratorWithOperators<T> implements IterableIterator<T> {
        /**
         * @param source Iterator to wrap
         */
        constructor(private source: Iterator<T>) {}
    
        /**
         * Returns a `{ value, done }` object that adheres to the Iterator protocol
         */
        next(): IteratorResult<T> {
            return this.source.next()
        }
    
        /**
         * The presence of this method makes the Iterator itself Iterable.
         * This makes it possible to pass it to `for of` and Iterable-accepting functions like `Array.from()`
         */
        [Symbol.iterator](): this {
            return this
        }
    
        /**
         * Returns a new Iterator by running each element thru iteratee
         */
        map<R>(iteratee: (value: T) => R): IteratorWithOperators<R> {
            return new IteratorWithOperators(new MapIterator(this.source, iteratee))
        }
    ....
    

    能看出其实现了[Symbol.iterator]的方法,所以是可遍历的。

    我们看下map操作的实现就明白为何会只迭代一次。直接看
    new MapIterator(this.source, iteratee)

    export class MapIterator<T, R> implements Iterator<R> {
        constructor(private source: Iterator<T>, private iteratee: (value: T) => R) {}
    
        next(): IteratorResult<R> {
            const { value, done } = this.source.next()
            return { value: !done && this.iteratee(value), done } as IteratorResult<R>
        }
    }
    

    可以看出,实例生成时,支撑保存了遍历器与处理方法。

    所以当最后调用IteratorWithOperators的非操作符的遍历方法时,会自动去调用遍历器的next方法,从最底层开始,一层一层的往上调用操作符的逻辑,所以最底层遍历结束,整体也进入最后结束轮,仅需遍历一次。

    PS: 也可以看出所有逻辑都是同步的。其实使用RxJS也是可以只遍历一次,如:

    of([1,2,3,4]).pipe(tap(....),map(...),mergeMap(....)).subscribe(cb)
    

    但这个包可以让我们类似用原生的方法去操作,比较亲切。

    如果觉得文章对你有点用的话,麻烦拿出手机,这里有一个你我都有的小福利(每天一次): 打开支付宝首页搜索“8601304”,即可领红包。谢谢支持

    相关文章

      网友评论

          本文标题:小工具iterate学习(加快类数组的遍历速度)

          本文链接:https://www.haomeiwen.com/subject/vfdybftx.html