refactored linq
This commit is contained in:
Родитель
7b0398e17a
Коммит
cb7d1a45a9
|
@ -178,7 +178,7 @@ export function pall<T, U>(array: Array<T>, callbackfn: (value: T, index: number
|
||||||
|
|
||||||
export function deconstruct(identifier: string | Array<string>): Array<string> {
|
export function deconstruct(identifier: string | Array<string>): Array<string> {
|
||||||
if (Array.isArray(identifier)) {
|
if (Array.isArray(identifier)) {
|
||||||
return [...values(identifier).linq.selectMany(deconstruct)];
|
return [...values(identifier).selectMany(deconstruct)];
|
||||||
}
|
}
|
||||||
return identifier.
|
return identifier.
|
||||||
replace(/([a-z]+)([A-Z])/g, '$1 $2').
|
replace(/([a-z]+)([A-Z])/g, '$1 $2').
|
||||||
|
|
|
@ -119,11 +119,11 @@ export class Schema extends Extensions implements Schema {
|
||||||
|
|
||||||
export function getPolymorphicBases(schema: Schema): Array<Schema> {
|
export function getPolymorphicBases(schema: Schema): Array<Schema> {
|
||||||
// are any of my parents polymorphic directly, or any of their parents?
|
// are any of my parents polymorphic directly, or any of their parents?
|
||||||
return [...values(schema.allOf).linq.where(parent => parent.discriminator ? true : false), ...values(schema.allOf).linq.selectMany(getPolymorphicBases)];
|
return [...values(schema.allOf).where(parent => parent.discriminator ? true : false), ...values(schema.allOf).selectMany(getPolymorphicBases)];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAllProperties(schema: Schema): Array<Property> {
|
export function getAllProperties(schema: Schema): Array<Property> {
|
||||||
return [...values(schema.allOf).linq.selectMany(getAllProperties), ...values(schema.properties)];
|
return [...values(schema.allOf).selectMany(getAllProperties), ...values(schema.properties)];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAllPublicVirtualProperties(virtualProperties?: VirtualProperties): Array<VirtualProperty> {
|
export function getAllPublicVirtualProperties(virtualProperties?: VirtualProperties): Array<VirtualProperty> {
|
||||||
|
@ -133,7 +133,7 @@ export function getAllPublicVirtualProperties(virtualProperties?: VirtualPropert
|
||||||
inlined: []
|
inlined: []
|
||||||
};
|
};
|
||||||
|
|
||||||
return [...values([...props.owned, ...props.inherited, ...props.inlined]).linq.where(each => !each.private)];
|
return [...values([...props.owned, ...props.inherited, ...props.inlined]).where(each => !each.private)];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAllVirtualProperties(virtualProperties?: VirtualProperties): Array<VirtualProperty> {
|
export function getAllVirtualProperties(virtualProperties?: VirtualProperties): Array<VirtualProperty> {
|
||||||
|
@ -152,7 +152,7 @@ export function getVirtualPropertyFromPropertyName(virtualProperties: VirtualPro
|
||||||
inherited: [],
|
inherited: [],
|
||||||
inlined: []
|
inlined: []
|
||||||
};
|
};
|
||||||
return values([...props.owned, ...props.inherited, ...props.inlined]).linq.first(each => each.property.serializedName === propertyName);
|
return values([...props.owned, ...props.inherited, ...props.inlined]).first(each => each.property.serializedName === propertyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ export class MemoryFileSystem implements IFileSystem {
|
||||||
|
|
||||||
public constructor(files: Map<string, string>) {
|
public constructor(files: Map<string, string>) {
|
||||||
this.filesByUri = new Map<string, string>(
|
this.filesByUri = new Map<string, string>(
|
||||||
items(files).linq.select(
|
items(files).select(
|
||||||
each => [
|
each => [
|
||||||
ResolveUri(MemoryFileSystem.DefaultVirtualRootUri, each.key),
|
ResolveUri(MemoryFileSystem.DefaultVirtualRootUri, each.key),
|
||||||
each.value
|
each.value
|
||||||
|
@ -44,7 +44,7 @@ export class MemoryFileSystem implements IFileSystem {
|
||||||
|
|
||||||
async EnumerateFileUris(folderUri: string = MemoryFileSystem.DefaultVirtualRootUri): Promise<Array<string>> {
|
async EnumerateFileUris(folderUri: string = MemoryFileSystem.DefaultVirtualRootUri): Promise<Array<string>> {
|
||||||
// return await [...From(this.filesByUri.keys()).Where(uri => {
|
// return await [...From(this.filesByUri.keys()).Where(uri => {
|
||||||
return keys(this.filesByUri).linq.where(uri => {
|
return keys(this.filesByUri).where(uri => {
|
||||||
// in folder?
|
// in folder?
|
||||||
if (!uri.startsWith(folderUri)) {
|
if (!uri.startsWith(folderUri)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -53,7 +53,7 @@ export class MemoryFileSystem implements IFileSystem {
|
||||||
// not in subfolder?
|
// not in subfolder?
|
||||||
// return uri.substr(folderUri.length).indexOf("/") === -1;
|
// return uri.substr(folderUri.length).indexOf("/") === -1;
|
||||||
return uri.substr(folderUri.length).indexOf('/') === -1;
|
return uri.substr(folderUri.length).indexOf('/') === -1;
|
||||||
}).linq.toArray();
|
}).toArray();
|
||||||
//})];
|
//})];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
import { Dictionary, items, keys, values, any } from '@azure-tools/linq';
|
import { Dictionary, items } from '@azure-tools/linq';
|
||||||
|
|
||||||
export type JsonPointer = string;
|
export type JsonPointer = string;
|
||||||
export type JsonPointerTokens = Array<string>;
|
export type JsonPointerTokens = Array<string>;
|
||||||
|
|
|
@ -53,6 +53,6 @@ export class BlameTree {
|
||||||
// recurse
|
// recurse
|
||||||
todos.push(...todo.blaming);
|
todos.push(...todo.blaming);
|
||||||
}
|
}
|
||||||
return values(result).linq.distinct(x => JSON.stringify(x)).linq.toArray();
|
return values(result).distinct(x => JSON.stringify(x)).toArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
export interface Index<T> {
|
||||||
|
[key: number]: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Dictionary<T> {
|
||||||
|
[key: string]: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Dictionary<T> implements Dictionary<T> {
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ToDictionary<T>(keys: Array<string>, each: (index: string) => T) {
|
||||||
|
const result = new Dictionary<T>();
|
||||||
|
keys.map((v, i, a) => result[v] = each(v));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type IndexOf<T> = T extends Map<T, infer V> ? T : T extends Array<infer V> ? number : string;
|
|
@ -0,0 +1,9 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
export * from './new-linq';
|
||||||
|
export * from './freeze';
|
||||||
|
export * from './visitor';
|
||||||
|
export * from './common';
|
|
@ -0,0 +1,301 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
import { IndexOf, Dictionary } from './common';
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reverses the elements in an Array.
|
||||||
|
* reverse(): T[];
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
export interface IterableWithLinq<T> extends Iterable<T> {
|
||||||
|
linq: IterableWithLinq<T>;
|
||||||
|
any(predicate?: (each: T) => boolean): boolean;
|
||||||
|
all(predicate: (each: T) => boolean): boolean;
|
||||||
|
bifurcate(predicate: (each: T) => boolean): Array<Array<T>>;
|
||||||
|
concat(more: Iterable<T>): IterableWithLinq<T>;
|
||||||
|
distinct(selector?: (each: T) => any): IterableWithLinq<T>;
|
||||||
|
first(predicate?: (each: T) => boolean): T | undefined;
|
||||||
|
selectNonNullable<V>(selector: (each: T) => V): IterableWithLinq<NonNullable<V>>;
|
||||||
|
select<V>(selector: (each: T) => V): IterableWithLinq<V>;
|
||||||
|
selectMany<V>(selector: (each: T) => Iterable<V>): IterableWithLinq<V>;
|
||||||
|
where(predicate: (each: T) => boolean): IterableWithLinq<T>;
|
||||||
|
forEach(action: (each: T) => void): void;
|
||||||
|
aggregate<A, R>(accumulator: (current: T | A, next: T) => A, seed?: T | A, resultAction?: (result?: T | A) => A | R): T | A | R | undefined;
|
||||||
|
toArray(): Array<T>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets or sets the length of the iterable. This is a number one higher than the highest element defined in an array.
|
||||||
|
*/
|
||||||
|
count(): number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds all the elements of an array separated by the specified separator string.
|
||||||
|
* @param separator A string used to separate one element of an array from the next in the resulting String. If omitted, the array elements are separated with a comma.
|
||||||
|
*/
|
||||||
|
join(separator?: string): string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
function linqify<T>(iterable: Iterable<T>): IterableWithLinq<T> {
|
||||||
|
if ((<any>iterable)['linq'] === iterable) {
|
||||||
|
return <IterableWithLinq<T>>iterable;
|
||||||
|
}
|
||||||
|
const r = <any>{
|
||||||
|
[Symbol.iterator]: iterable[Symbol.iterator].bind(iterable),
|
||||||
|
all: <any>all.bind(iterable),
|
||||||
|
any: <any>any.bind(iterable),
|
||||||
|
bifurcate: <any>bifurcate.bind(iterable),
|
||||||
|
concat: <any>concat.bind(iterable),
|
||||||
|
distinct: <any>distinct.bind(iterable),
|
||||||
|
first: <any>first.bind(iterable),
|
||||||
|
select: <any>select.bind(iterable),
|
||||||
|
selectMany: <any>selectMany.bind(iterable),
|
||||||
|
selectNonNullable: <any>selectNonNullable.bind(iterable),
|
||||||
|
toArray: <any>toArray.bind(iterable),
|
||||||
|
where: <any>where.bind(iterable),
|
||||||
|
forEach: <any>forEach.bind(iterable),
|
||||||
|
aggregate: <any>aggregate.bind(iterable),
|
||||||
|
join: <any>join.bind(iterable),
|
||||||
|
count: len.bind(iterable)
|
||||||
|
};
|
||||||
|
r.linq = r;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
function len<T>(this: Iterable<T>): number {
|
||||||
|
return length(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** returns an IterableWithLinq<> for keys in the collection */
|
||||||
|
export function keys<K, T, TSrc extends (Array<T> | Dictionary<T> | Map<K, T>)>(source: TSrc & (Array<T> | Dictionary<T> | Map<K, T>) | null | undefined): IterableWithLinq<IndexOf<TSrc>> {
|
||||||
|
if (source) {
|
||||||
|
if (Array.isArray(source)) {
|
||||||
|
return <IterableWithLinq<IndexOf<TSrc>>>linqify((<Array<T>>source).keys());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source instanceof Map) {
|
||||||
|
return <IterableWithLinq<IndexOf<TSrc>>><unknown>linqify((<Map<K, T>>source).keys());
|
||||||
|
}
|
||||||
|
|
||||||
|
return <IterableWithLinq<IndexOf<TSrc>>>linqify((Object.getOwnPropertyNames(source)));
|
||||||
|
}
|
||||||
|
// undefined/null
|
||||||
|
return linqify([]);
|
||||||
|
}
|
||||||
|
function isIterable<T>(source: any): source is Iterable<T> {
|
||||||
|
return !!source && !!source[Symbol.iterator];
|
||||||
|
}
|
||||||
|
/** returns an IterableWithLinq<> for values in the collection */
|
||||||
|
export function values<K, T, TSrc extends (Array<T> | Dictionary<T> | Map<K, T>)>(source: (Iterable<T> | Array<T> | Dictionary<T> | Map<K, T>) | null | undefined): IterableWithLinq<T> {
|
||||||
|
if (source) {
|
||||||
|
// map
|
||||||
|
if (source instanceof Map) {
|
||||||
|
return linqify(source.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
// any iterable source
|
||||||
|
if (isIterable(source)) {
|
||||||
|
return linqify(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
// dictionary (object keys)
|
||||||
|
return linqify(function* () {
|
||||||
|
for (const key of keys(source)) {
|
||||||
|
const value = source[key];
|
||||||
|
if (typeof value !== 'function') {
|
||||||
|
yield value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// null/undefined
|
||||||
|
return linqify([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** returns an IterableWithLinq<{key,value}> for the source */
|
||||||
|
export function items<K, T, TSrc extends (Array<T> | Dictionary<T> | Map<K, T>)>(source: TSrc & (Array<T> | Dictionary<T> | Map<K, T>) | null | undefined): IterableWithLinq<{ key: IndexOf<TSrc>; value: T }> {
|
||||||
|
if (source) {
|
||||||
|
if (Array.isArray(source)) {
|
||||||
|
return <IterableWithLinq<{ key: IndexOf<TSrc>; value: T }>>linqify(function* () { for (let i = 0; i < source.length; i++) { yield { key: i, value: source[i] }; } }());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source instanceof Map) {
|
||||||
|
return <IterableWithLinq<{ key: IndexOf<TSrc>; value: T }>>linqify(function* () { for (const [key, value] of source.entries()) { yield { key, value }; } }());
|
||||||
|
}
|
||||||
|
|
||||||
|
return <IterableWithLinq<{ key: IndexOf<TSrc>; value: T }>><unknown>linqify(function* () {
|
||||||
|
for (const key of keys(source)) {
|
||||||
|
const value = source[<string>key];
|
||||||
|
if (typeof value !== 'function') {
|
||||||
|
yield {
|
||||||
|
key, value: source[<string>key]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
// undefined/null
|
||||||
|
return linqify([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function length<T, K>(source?: Iterable<T> | Dictionary<T> | Array<T> | Map<K, T>): number {
|
||||||
|
if (source) {
|
||||||
|
if (Array.isArray(source)) {
|
||||||
|
return source.length;
|
||||||
|
}
|
||||||
|
if (source instanceof Map) {
|
||||||
|
return source.size;
|
||||||
|
}
|
||||||
|
if (isIterable(source)) {
|
||||||
|
return [...source].length;
|
||||||
|
}
|
||||||
|
return source ? Object.getOwnPropertyNames(source).length : 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function any<T>(this: Iterable<T>, predicate?: (each: T) => boolean): boolean {
|
||||||
|
for (const each of this) {
|
||||||
|
if (!predicate || predicate(each)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function all<T>(this: Iterable<T>, predicate: (each: T) => boolean): boolean {
|
||||||
|
for (const each of this) {
|
||||||
|
if (!predicate(each)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function concat<T>(this: Iterable<T>, more: Iterable<T>): IterableWithLinq<T> {
|
||||||
|
return linqify(function* (this: Iterable<T>) {
|
||||||
|
for (const each of this) {
|
||||||
|
yield each;
|
||||||
|
}
|
||||||
|
for (const each of more) {
|
||||||
|
yield each;
|
||||||
|
}
|
||||||
|
}.bind(this)());
|
||||||
|
}
|
||||||
|
|
||||||
|
function select<T, V>(this: Iterable<T>, selector: (each: T) => V): IterableWithLinq<V> {
|
||||||
|
return linqify(function* (this: Iterable<T>) {
|
||||||
|
for (const each of this) {
|
||||||
|
yield selector(each);
|
||||||
|
}
|
||||||
|
}.bind(this)());
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectMany<T, V>(this: Iterable<T>, selector: (each: T) => Iterable<V>): IterableWithLinq<V> {
|
||||||
|
return linqify(function* (this: Iterable<T>) {
|
||||||
|
for (const each of this) {
|
||||||
|
for (const item of selector(each)) {
|
||||||
|
yield item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.bind(this)());
|
||||||
|
}
|
||||||
|
|
||||||
|
function where<T>(this: Iterable<T>, predicate: (each: T) => boolean): IterableWithLinq<T> {
|
||||||
|
return linqify(function* (this: Iterable<T>) {
|
||||||
|
for (const each of this) {
|
||||||
|
if (predicate(each)) {
|
||||||
|
yield each;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.bind(this)());
|
||||||
|
}
|
||||||
|
|
||||||
|
function forEach<T>(this: Iterable<T>, action: (each: T) => void) {
|
||||||
|
for (const each of this) {
|
||||||
|
action(each);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function aggregate<T, A, R>(this: Iterable<T>, accumulator: (current: T | A, next: T) => A, seed?: T | A, resultAction?: (result?: T | A) => A | R): T | A | R | undefined {
|
||||||
|
let result: T | A | undefined = seed;
|
||||||
|
for (const each of this) {
|
||||||
|
if (result === undefined) {
|
||||||
|
result = each;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result = accumulator(result, each);
|
||||||
|
}
|
||||||
|
return resultAction !== undefined ? resultAction(result) : result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectNonNullable<T, V>(this: Iterable<T>, selector: (each: T) => V): IterableWithLinq<NonNullable<V>> {
|
||||||
|
return linqify(function* (this: Iterable<T>) {
|
||||||
|
for (const each of this) {
|
||||||
|
const value = selector(each);
|
||||||
|
if (value) {
|
||||||
|
yield <NonNullable<V>><any>value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.bind(this)());
|
||||||
|
}
|
||||||
|
|
||||||
|
function nonNullable<T>(this: Iterable<T>): IterableWithLinq<NonNullable<T>> {
|
||||||
|
return linqify(function* (this: Iterable<T>) {
|
||||||
|
for (const each of this) {
|
||||||
|
if (each) {
|
||||||
|
yield <NonNullable<T>><any>each;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.bind(this)());
|
||||||
|
}
|
||||||
|
|
||||||
|
function first<T>(this: Iterable<T>, predicate?: (each: T) => boolean): T | undefined {
|
||||||
|
for (const each of this) {
|
||||||
|
if (!predicate || predicate(each)) {
|
||||||
|
return each;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function toArray<T>(this: Iterable<T>): Array<T> {
|
||||||
|
return [...this];
|
||||||
|
}
|
||||||
|
|
||||||
|
function join<T>(this: Iterable<T>, separator: string): string {
|
||||||
|
return [...this].join(separator);
|
||||||
|
}
|
||||||
|
|
||||||
|
function bifurcate<T>(this: Iterable<T>, predicate: (each: T) => boolean): Array<Array<T>> {
|
||||||
|
const result = [new Array<T>(), new Array<T>()];
|
||||||
|
for (const each of this) {
|
||||||
|
result[predicate(each) ? 0 : 1].push(each);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function distinct<T>(this: Iterable<T>, selector?: (each: T) => any): IterableWithLinq<T> {
|
||||||
|
const hash = new Dictionary<boolean>();
|
||||||
|
return linqify(function* (this: Iterable<T>) {
|
||||||
|
|
||||||
|
if (!selector) {
|
||||||
|
selector = i => i;
|
||||||
|
}
|
||||||
|
for (const each of this) {
|
||||||
|
const k = JSON.stringify(selector(each));
|
||||||
|
if (!hash[k]) {
|
||||||
|
hash[k] = true;
|
||||||
|
yield each;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.bind(this)());
|
||||||
|
}
|
|
@ -2,28 +2,24 @@
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
export * from './freeze';
|
import { IndexOf, Dictionary } from './common';
|
||||||
export * from './visitor';
|
|
||||||
|
|
||||||
export interface Index<T> {
|
export interface Linqed<T> extends Iterable<T> {
|
||||||
[key: number]: T;
|
any(predicate?: (each: T) => boolean): boolean;
|
||||||
|
all(predicate: (each: T) => boolean): boolean;
|
||||||
|
bifurcate(predicate: (each: T) => boolean): Array<Array<T>>;
|
||||||
|
concat(more: Iterable<T>): Linqable<T>;
|
||||||
|
distinct(selector?: (each: T) => any): Linqable<T>;
|
||||||
|
first(predicate?: (each: T) => boolean): T | undefined;
|
||||||
|
selectNonNullable<V>(selector: (each: T) => V): Linqable<NonNullable<V>>;
|
||||||
|
select<V>(selector: (each: T) => V): Linqable<V>;
|
||||||
|
selectMany<V>(selector: (each: T) => Iterable<V>): Linqable<V>;
|
||||||
|
where(predicate: (each: T) => boolean): Linqable<T>;
|
||||||
|
forEach(action: (each: T) => void): void;
|
||||||
|
aggregate<A, R>(accumulator: (current: T | A, next: T) => A, seed?: T | A, resultAction?: (result?: T | A) => A | R): T | A | R | undefined;
|
||||||
|
toArray(): Array<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Dictionary<T> {
|
|
||||||
[key: string]: T;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Dictionary<T> implements Dictionary<T> {
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ToDictionary<T>(keys: Array<string>, each: (index: string) => T) {
|
|
||||||
const result = new Dictionary<T>();
|
|
||||||
keys.map((v, i, a) => result[v] = each(v));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type IndexOf<T> = T extends Map<T, infer V> ? T : T extends Array<infer V> ? number : string;
|
|
||||||
|
|
||||||
export interface Linqable<T> extends Iterable<T> {
|
export interface Linqable<T> extends Iterable<T> {
|
||||||
linq: {
|
linq: {
|
||||||
any(predicate?: (each: T) => boolean): boolean;
|
any(predicate?: (each: T) => boolean): boolean;
|
||||||
|
@ -41,14 +37,33 @@ export interface Linqable<T> extends Iterable<T> {
|
||||||
toArray(): Array<T>;
|
toArray(): Array<T>;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
function enlinq<T>(iterable: Iterable<T>): Linqed<T> {
|
||||||
|
return {
|
||||||
|
...iterable,
|
||||||
|
all: <any>all.bind(iterable),
|
||||||
|
any: <any>any.bind(iterable),
|
||||||
|
bifurcate: <any>bifurcate.bind(iterable),
|
||||||
|
concat: <any>concat.bind(iterable),
|
||||||
|
distinct: <any>distinct.bind(iterable),
|
||||||
|
first: <any>first.bind(iterable),
|
||||||
|
select: <any>select.bind(iterable),
|
||||||
|
selectMany: <any>selectMany.bind(iterable),
|
||||||
|
selectNonNullable: <any>selectNonNullable.bind(iterable),
|
||||||
|
toArray: <any>toArray.bind(iterable),
|
||||||
|
where: <any>where.bind(iterable),
|
||||||
|
forEach: <any>forEach.bind(iterable),
|
||||||
|
aggregate: <any>aggregate.bind(iterable),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function linqify<T>(iterable: Iterable<T>): Linqable<T> {
|
function linqify<T>(iterable: Iterable<T>): Linqable<T> {
|
||||||
if (!!(<any>iterable)['linq']) {
|
if ((<any>iterable)['linq']) {
|
||||||
return <Linqable<T>>iterable;
|
return <Linqable<T>>iterable;
|
||||||
}
|
}
|
||||||
return Object.defineProperty(iterable, 'linq', {
|
return Object.defineProperty(iterable, 'linq', {
|
||||||
get: () => {
|
get: () => {
|
||||||
/* eslint-disable */
|
|
||||||
return {
|
return {
|
||||||
all: all.bind(iterable),
|
all: all.bind(iterable),
|
||||||
any: any.bind(iterable),
|
any: any.bind(iterable),
|
||||||
|
@ -111,10 +126,41 @@ export function values<K, T, TSrc extends (Array<T> | Dictionary<T> | Map<K, T>)
|
||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// null/undefined
|
// null/undefined
|
||||||
return linqify([]);
|
return linqify([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** returns an Linqable<> for values in the collection */
|
||||||
|
export function evalues<K, T, TSrc extends (Array<T> | Dictionary<T> | Map<K, T>)>(source: (Iterable<T> | Array<T> | Dictionary<T> | Map<K, T>) | null | undefined): Linqed<T> {
|
||||||
|
if (source) {
|
||||||
|
// map
|
||||||
|
if (source instanceof Map) {
|
||||||
|
return enlinq(source.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
// any iterable source
|
||||||
|
if (isIterable(source)) {
|
||||||
|
return enlinq(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
// dictionary (object keys)
|
||||||
|
return enlinq(function* () {
|
||||||
|
for (const key of keys(source)) {
|
||||||
|
const value = source[key];
|
||||||
|
if (typeof value !== 'function') {
|
||||||
|
yield value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// null/undefined
|
||||||
|
return enlinq([]);
|
||||||
|
}
|
||||||
|
|
||||||
/** returns an Linqable<{key,value}> for the Collection */
|
/** returns an Linqable<{key,value}> for the Collection */
|
||||||
export function items<K, T, TSrc extends (Array<T> | Dictionary<T> | Map<K, T>)>(source: TSrc & (Array<T> | Dictionary<T> | Map<K, T>) | null | undefined): Linqable<{ key: IndexOf<TSrc>; value: T }> {
|
export function items<K, T, TSrc extends (Array<T> | Dictionary<T> | Map<K, T>)>(source: TSrc & (Array<T> | Dictionary<T> | Map<K, T>) | null | undefined): Linqable<{ key: IndexOf<TSrc>; value: T }> {
|
||||||
if (source) {
|
if (source) {
|
|
@ -3,8 +3,8 @@
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"patchOffset": 100,
|
"patchOffset": 100,
|
||||||
"description": "LINQ-like functionality for Typescript.",
|
"description": "LINQ-like functionality for Typescript.",
|
||||||
"main": "./dist/main.js",
|
"main": "./dist/exports.js",
|
||||||
"typings": "./dist/main.d.ts",
|
"typings": "./dist/exports.d.ts",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10.12.0"
|
"node": ">=10.12.0"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { suite, test, slow, timeout, skip, only } from 'mocha-typescript';
|
import { suite, test, slow, timeout, skip, only } from 'mocha-typescript';
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import { values, length } from '../main';
|
import { values, length, evalues, } from '../old-linq';
|
||||||
|
|
||||||
@suite class MyTests {
|
@suite class MyTests {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { suite, test, slow, timeout, skip, only } from 'mocha-typescript';
|
||||||
|
import * as assert from 'assert';
|
||||||
|
import { values, length, } from '../new-linq';
|
||||||
|
|
||||||
|
@suite class NewLinq {
|
||||||
|
|
||||||
|
private anArray = ['A', 'B', 'C', 'D', 'E'];
|
||||||
|
|
||||||
|
@test async 'distinct'() {
|
||||||
|
|
||||||
|
const items = ['one', 'two', 'two', 'three'];
|
||||||
|
const distinct = values(items).distinct().toArray();
|
||||||
|
assert.equal(length(distinct), 3);
|
||||||
|
|
||||||
|
const dic = {
|
||||||
|
happy: 'hello',
|
||||||
|
sad: 'hello',
|
||||||
|
more: 'name',
|
||||||
|
maybe: 'foo',
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = values(dic).distinct().toArray();
|
||||||
|
assert.equal(length(distinct), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@test async 'iterating thru collections'() {
|
||||||
|
// items are items.
|
||||||
|
assert.equal([...values(this.anArray)].join(','), this.anArray.join(','));
|
||||||
|
|
||||||
|
assert.equal(values(this.anArray).count(), 5);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче