Greasy Fork

LINQ

Linq for javascript

目前为 2018-12-28 提交的版本。查看 最新版本

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.greasyfork.icu/scripts/376052/657567/LINQ.js

// ==UserScript==
// @name         LINQ
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Linq for javascript
// @author       You
// @grant        none
// ==/UserScript==

class Enumerable{
    constructor(iterable,isClosure=true){
        this.iterable=isClosure?iterable():iterable;
        this.extends=[];
    }

    *[Symbol.iterator](){
        let cache=[];
        for(let x of this.iterable){
            cache.push(x);
            yield x;
        }
        for(let x of this.extends){
            cache.push(x);
            yield x;
        }
        this.iterable=cache;
    }

    where(predicate){
        let a=this;
        return new Enumerable(function*(){
            for (let x of a){
                if (predicate(a)){
                    yield x;
                }
            }
        });
    }

    count(predicate){
        predicate=predicate || function(){return true;};
        let count=0;
        for(let x of this){
            if (predicate(x)){
                count+=1;
            }
        }
        return count;
    }

    first(predicate){
        predicate=predicate || function(){return true;};
        for(let x of this){
            if (predicate(x)){
                return x;
            }
        }
        throw "Sequence least than 1";
    }

    firstOrDefault(predicate){
        try {
            return this.first();
        }
        catch(e){
            return null;
        }
    }

    elementAt(n){
        let id=0;
        for (let x of this){
            if (id==n){
                return x;
            }
            id++;
        }
        throw "Index of found";
    }

    select(selector){
        let a=this;
        return new Enumerable(function*(){
            for(let x of a){
                yield selector(x);
            }
        });
    }

    join(object,outerSelector,innerSelector,selector){
        let a=this;
        return new Enumerable(function*(){
            for(let x of a){
                for(let y of object){
                    if (outerSelector(x)==innerSelector(y)){
                        yield selector(x,y);
                    }
                }
            }
        });
    }

    groupBy(selector){
        let a=this.toArray();
        return new Enumerable(function*(){
            while (a.length!=0){
                let key=selector(a[0]);
                yield new Grouping(key,a.filter(function(x){return selector(x)==key;}));
                a=a.filter(function(x){return selector(x)!=key;});
            }
        });
    }

    toEnumerable(){
        return new Enumerable(this,false);
    }

    toArray(){
        let result=[];
        for(let x of this){
            result.push(x);
        }
        return result;
    }

    each(action){
        for (let x of this){
            action(x);
        }
    }

    aggregate(func,initValue=null){
        let isSetInit=false;
        let accu=null;
        if (initValue!=null){
            accu=initValue;
            isSetInit=false;
        }
        for (let x of this){
            if (!isSetInit && accu==null){
                accu=x;
                continue;
            }
            accu=func(accu,x);
        }
        if (accu==null){
            throw "Sequence less than 1";
        }
        return accu;
    }

    sum(selector){
        selector=selector || function(x){return x;};
        return this.select(selector).aggregate(function(accu,next){return accu+next;},0);
    }

    max(selector){
        selector=selector || function(x){return x;};
        return this.select(selector).aggregate(function(accu,next){return accu>next?accu:next;});
    }

    min(selector){
        selector=selector || function(x){return x;};
        return this.select(selector).aggregate(function(accu,next){return accu<next?accu:next;});
    }

    unique(selector){
        return this.groupBy(selector).select(function(x){return x.first();});
    }

    static from(iterable){
        return new Enumerable(iterable,false);
    }

    static range(from,to){
        return new Enumerable(function*(){
            for(let i=from;i<to;i++){
                yield i;
            }
        });
    }

    static repeat(object,count){
        return new Enumerable(function*(){
            for(let i=0;i<count;i++){
                yield object;
            }
        });
    }
}

class Grouping extends Enumerable {
    constructor(key, iterable) {
        super(iterable,false);
        this.key = key;
    }
}