Skip to content

Commit

Permalink
feat(iterables): Add index to callbacks
Browse files Browse the repository at this point in the history
Add index argument to iterable callbacks.

re #11
  • Loading branch information
danielrbradley committed Jul 24, 2018
1 parent 3fcf761 commit 7e7cce4
Show file tree
Hide file tree
Showing 2 changed files with 184 additions and 36 deletions.
118 changes: 82 additions & 36 deletions src/iterables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,23 @@ export function toArray<T>(source: Iterable<T>): T[] {
* Creates a new iterable whose elements are the results of applying the specified mapping to each of the elements of the source collection.
* @param mapping A function to transform items from the input collection.
*/
export function map<T, U>(mapping: (item: T) => U): (source: Iterable<T>) => Iterable<U>
export function map<T, U>(
mapping: (item: T, index: number) => U
): (source: Iterable<T>) => Iterable<U>
/**
* Creates a new iterable whose elements are the results of applying the specified mapping to each of the elements of the source collection.
* @param source The input collection.
* @param mapping A function to transform items from the input collection.
*/
export function map<T, U>(source: Iterable<T>, mapping: (item: T) => U): Iterable<U>
export function map<T, U>(source: Iterable<T>, mapping: (item: T, index: number) => U): Iterable<U>
export function map<T, U>(a: any, b?: any): any {
const partial = typeof a === 'function'
const mapping: (item: T) => U = partial ? a : b
const mapping: (item: T, index: number) => U = partial ? a : b
function* exec(source: Iterable<T>) {
let index = 0
for (const item of source) {
yield mapping(item)
yield mapping(item, index)
index++
}
}
return partial ? exec : exec(a)
Expand All @@ -32,21 +36,28 @@ export function map<T, U>(a: any, b?: any): any {
* Returns a new iterable containing only the elements of the collection for which the given predicate returns true.
* @param predicate A function to test whether each item in the input collection should be included in the output.
*/
export function filter<T>(predicate: (item: T) => boolean): (source: Iterable<T>) => Iterable<T>
export function filter<T>(
predicate: (item: T, index: number) => boolean
): (source: Iterable<T>) => Iterable<T>
/**
* Returns a new iterable containing only the elements of the collection for which the given predicate returns true.
* @param source The input collection.
* @param predicate A function to test whether each item in the input collection should be included in the output.
*/
export function filter<T>(source: Iterable<T>, predicate: (item: T) => boolean): Iterable<T>
export function filter<T>(
source: Iterable<T>,
predicate: (item: T, index: number) => boolean
): Iterable<T>
export function filter<T>(a: any, b?: any): any {
const partial = typeof a === 'function'
const predicate: (item: T) => boolean = partial ? a : b
const predicate: (item: T, index: number) => boolean = partial ? a : b
function* exec(source: Iterable<T>) {
let index = 0
for (const item of source) {
if (predicate(item)) {
if (predicate(item, index)) {
yield item
}
index++
}
}
return partial ? exec : exec(a)
Expand All @@ -57,23 +68,28 @@ export function filter<T>(a: any, b?: any): any {
* @param chooser A function to transform items from the input collection to a new value to be included, or undefined to be excluded.
*/
export function choose<T, U>(
chooser: (item: T) => U | undefined
chooser: (item: T, index: number) => U | undefined
): (source: Iterable<T>) => Iterable<U>
/**
* Applies the given function to each element of the sequence and returns a new sequence comprised of the results for each element where the function returns a value.
* @param source The input collection.
* @param chooser A function to transform items from the input collection to a new value to be included, or undefined to be excluded.
*/
export function choose<T, U>(source: Iterable<T>, chooser: (item: T) => U | undefined): Iterable<U>
export function choose<T, U>(
source: Iterable<T>,
chooser: (item: T, index: number) => U | undefined
): Iterable<U>
export function choose<T, U>(a: any, b?: any): any {
const partial = typeof a === 'function'
const chooser: (item: T) => U | undefined = partial ? a : b
const chooser: (item: T, index: number) => U | undefined = partial ? a : b
function* exec(source: Iterable<T>) {
let index = 0
for (const item of source) {
const chosen = chooser(item)
const chosen = chooser(item, index)
if (chosen !== undefined) {
yield chosen
}
index++
}
}
return partial ? exec : exec(a)
Expand All @@ -84,23 +100,28 @@ export function choose<T, U>(a: any, b?: any): any {
* @param mapping A function to transform elements of the input collection into collections that are concatenated.
*/
export function collect<T, U>(
mapping: (item: T) => Iterable<U>
mapping: (item: T, index: number) => Iterable<U>
): (source: Iterable<T>) => Iterable<U>
/**
* Applies the given function to each element of the source iterable and concatenates all the results.
* @param source The input collection.
* @param mapping A function to transform elements of the input collection into collections that are concatenated.
*/
export function collect<T, U>(source: Iterable<T>, mapping: (item: T) => Iterable<U>): Iterable<U>
export function collect<T, U>(
source: Iterable<T>,
mapping: (item: T, index: number) => Iterable<U>
): Iterable<U>
export function collect<T, U>(a: any, b?: any): any {
const partial = typeof a === 'function'
const mapping: (item: T) => Iterable<U> = partial ? a : b
const mapping: (item: T, index: number) => Iterable<U> = partial ? a : b
function* exec(source: Iterable<T>) {
let index = 0
for (const item of source) {
const children = mapping(item)
const children = mapping(item, index)
for (const child of children) {
yield child
}
index++
}
}
return partial ? exec : exec(a)
Expand Down Expand Up @@ -151,26 +172,33 @@ export function* concat<T>(sources: Iterable<Iterable<T>>): Iterable<T> {
* @param selector A function that transforms the collection items into comparable keys.
* @param source The input collection.
*/
export function distinctBy<T, Key>(selector: (item: T) => Key): (source: Iterable<T>) => Iterable<T>
export function distinctBy<T, Key>(
selector: (item: T, index: number) => Key
): (source: Iterable<T>) => Iterable<T>
/**
* Returns a iterable that contains no duplicate entries according to the equality comparisons on
* the keys returned by the given key-generating function. If an element occurs multiple times in
* the sequence then the later occurrences are discarded.
* @param source The input collection.
* @param selector A function that transforms the collection items into comparable keys.
*/
export function distinctBy<T, Key>(source: Iterable<T>, selector: (item: T) => Key): Iterable<T>
export function distinctBy<T, Key>(
source: Iterable<T>,
selector: (item: T, index: number) => Key
): Iterable<T>
export function distinctBy<T, Key>(a: any, b?: any): any {
const partial = typeof a === 'function'
const selector: (item: T) => Key = partial ? a : b
const selector: (item: T, index: number) => Key = partial ? a : b
function* exec(source: Iterable<T>): Iterable<T> {
const seen = new Set<Key>()
let index = 0
for (const item of source) {
const key = selector(item)
const key = selector(item, index)
if (!seen.has(key)) {
seen.add(key)
yield item
}
index++
}
}
return partial ? exec : exec(a)
Expand All @@ -181,21 +209,28 @@ export function distinctBy<T, Key>(a: any, b?: any): any {
* @param predicate A function to test each item of the input collection.
* @param source The input collection.
*/
export function exists<T>(predicate: (item: T) => boolean): (source: Iterable<T>) => boolean
export function exists<T>(
predicate: (item: T, index: number) => boolean
): (source: Iterable<T>) => boolean
/**
* Tests if any element of the collection satisfies the given predicate.
* @param source The input collection.
* @param predicate A function to test each item of the input collection.
*/
export function exists<T>(source: Iterable<T>, predicate: (item: T) => boolean): boolean
export function exists<T>(
source: Iterable<T>,
predicate: (item: T, index: number) => boolean
): boolean
export function exists<T>(a: any, b?: any): any {
const partial = typeof a === 'function'
const predicate: (item: T) => boolean = partial ? a : b
const predicate: (item: T, index: number) => boolean = partial ? a : b
function exec(source: Iterable<T>): boolean {
let index = 0
for (const item of source) {
if (predicate(item)) {
if (predicate(item, index)) {
return true
}
index++
}
return false
}
Expand All @@ -208,22 +243,24 @@ export function exists<T>(a: any, b?: any): any {
* @param source The input collection.
* @throws If no item is found matching the criteria of the predicate.
*/
export function get<T>(predicate: (item: T) => boolean): (source: Iterable<T>) => T
export function get<T>(predicate: (item: T, index: number) => boolean): (source: Iterable<T>) => T
/**
* Returns the first element for which the given function returns true.
* @param source The input collection.
* @param predicate A function to test whether an item in the collection should be returned.
* @throws If no item is found matching the criteria of the predicate.
*/
export function get<T>(source: Iterable<T>, predicate: (item: T) => boolean): T
export function get<T>(source: Iterable<T>, predicate: (item: T, index: number) => boolean): T
export function get<T>(a: any, b?: any): any {
const partial = typeof a === 'function'
const predicate: (item: T) => boolean = partial ? a : b
const predicate: (item: T, index: number) => boolean = partial ? a : b
function exec(source: Iterable<T>): T | undefined {
let index = 0
for (const item of source) {
if (predicate(item)) {
if (predicate(item, index)) {
return item
}
index++
}
throw new Error('Element not found matching criteria')
}
Expand All @@ -235,47 +272,56 @@ export function get<T>(a: any, b?: any): any {
* @param predicate A function to test whether an item in the collection should be returned.
* @param source The input collection.
*/
export function find<T>(predicate: (item: T) => boolean): (source: Iterable<T>) => T | undefined
export function find<T>(
predicate: (item: T, index: number) => boolean
): (source: Iterable<T>) => T | undefined
/**
* Returns the first element for which the given function returns true, otherwise undefined.
* @param source The input collection.
* @param predicate A function to test whether an item in the collection should be returned.
*/
export function find<T>(source: Iterable<T>, predicate: (item: T) => boolean): T | undefined
export function find<T>(
source: Iterable<T>,
predicate: (item: T, index: number) => boolean
): T | undefined
export function find<T>(a: any, b?: any): any {
const partial = typeof a === 'function'
const predicate: (item: T) => boolean = partial ? a : b
const predicate: (item: T, index: number) => boolean = partial ? a : b
function exec(source: Iterable<T>): T | undefined {
let index = 0
for (const item of source) {
if (predicate(item)) {
if (predicate(item, index)) {
return item
}
index++
}
return undefined
}
return partial ? exec : exec(a)
}

export function groupBy<T, Key>(
selector: (item: T) => Key
selector: (item: T, index: number) => Key
): (source: Iterable<T>) => Iterable<[Key, ReadonlyArray<T>]>
export function groupBy<T, Key>(
source: Iterable<T>,
selector: (item: T) => Key
selector: (item: T, index: number) => Key
): Iterable<[Key, Iterable<T>]>
export function groupBy<T, Key>(a: any, b?: any): any {
const partial = typeof a === 'function'
const selector: (item: T) => Key = partial ? a : b
const selector: (item: T, index: number) => Key = partial ? a : b
function exec(source: Iterable<T>): Iterable<[Key, ReadonlyArray<T>]> {
const groups = new Map<Key, T[]>()
let index = 0
for (const item of source) {
const key = selector(item)
const key = selector(item, index)
const group = groups.get(key)
if (group === undefined) {
groups.set(key, [item])
} else {
group.push(item)
}
index++
}
return groups.entries()
}
Expand Down
Loading

0 comments on commit 7e7cce4

Please sign in to comment.