Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,18 @@
"devDependencies": {
"@rollup/plugin-typescript": "^3.1.1",
"@types/fs-extra": "^9.0.0",
"@types/jest": "^25.2.2",
"@types/jest": "^25.2.3",
"@types/node": "^14.0.1",
"codecov": "^3.7.0",
"fast-check": "^1.24.2",
"fs-extra": "^9.0.0",
"istanbul": "^0.4.5",
"jest": "26.0.1",
"jest-junit": "^10.0.0",
"rollup": "^2.10.2",
"rollup": "^2.10.3",
"rxjs": "^6.5.4",
"semantic-release": "^17.0.7",
"terser": "^4.6.13",
"terser": "^4.7.0",
"ts-jest": "^26.0.0",
"ts-node": "^8.10.1",
"tslint": "^6.1.2",
Expand Down
76 changes: 76 additions & 0 deletions src/list/list.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
import { List } from './list'
import { listFrom } from './list.factory'

class Animal {
constructor(public name: string) { }
}
class Dog extends Animal {
dogtag!: string
dogyear!: number
}

class Cat extends Animal {
likesCatnip = true
}

describe(List.name, () => {
describe('Integers', () => {
Expand Down Expand Up @@ -169,11 +182,74 @@ describe(List.name, () => {
const sut = List.of('test 1', 'test 2', 'test 3')

expect(sut.any(a => a.includes('test'))).toEqual(true)
expect(sut.some(a => a.includes('test'))).toEqual(true)
})
it('should', () => {
const sut = List.of('test 1', 'UGH!', 'test 2', 'test 3')

expect(sut.any(a => a.includes('NOTHERE'))).toEqual(false)
expect(sut.some(a => a.includes('NOTHERE'))).toEqual(false)
})
})

describe('take', () => {
it('should ...', () => {
const sut = List.of(1, 2, 3)

expect(sut.take(3).toArray()).toEqual([1, 2, 3])
expect(sut.take(2).toArray()).toEqual([1, 2])
expect(sut.take(1).toArray()).toEqual([1])
expect(sut.take(0).toArray()).toEqual([])
})
})

describe('InstanceOf', () => {
it('should filter on instance', () => {
const dog = new Dog('Rex')
const cat = new Cat('Meow')
const sut = List.of<Animal>(dog, cat)

expect(sut.ofType(Cat).toArray().length).toEqual(1)
expect(sut.ofType(Cat).toArray()).toEqual([cat])
expect(sut.ofType(Dog).toArray().length).toEqual(1)
expect(sut.ofType(Dog).toArray()).toEqual([dog])
})
})

describe('Drop', () => {
it('should', () => {
const sut = List.of(1, 5, 10, 15, 20).drop(1).drop(1).toArray()
const sut2 = listFrom(sut).drop(2).toArray()
const sut3 = listFrom(sut2).tail().toArray()

expect(sut).toEqual([10, 15, 20])
expect(sut2).toEqual([20])
expect(sut3).toEqual([])
})
})

// describe('OrderBy', () => {
// it('should order by object', () => {
// const dog1 = new Dog('Atlas')
// const dog2 = new Dog('Zues')
// const sut = List.of<Dog>(dog1, dog2)

// expect(sut.orderBy('dogtag').toEqual([]))
// expect(sut.orderBy('name')).toEqual([])
// })

// it('should order by number', () => {
// const sut = List.of(1, 2, 5, 3, 12)

// expect(sut.orderBy().toEqual([]))
// expect(sut.orderBy()).toEqual([])
// })

// it('should order by string', () => {
// const sut = List.of('abc', 'efg', 'zel', 'lmao')

// expect(sut.orderBy().toEqual([]))
// expect(sut.orderBy()).toEqual([])
// })
// })
})
80 changes: 76 additions & 4 deletions src/list/list.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Repurposed from this great piece of code: https://gist.github.com/gvergnaud/6e9de8e06ef65e65f18dbd05523c7ca9
// Implements a number of functions from the .NET LINQ library: https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.reverse?view=netcore-3.1
// tslint:disable: no-let

/**
* A lazily evaluated list with useful extension methods.
Expand Down Expand Up @@ -40,7 +41,6 @@ export class List<T> {

public static range(start: number, end: number, step = 1): List<number> {
return new List(function* () {
// tslint:disable-next-line: no-let
let i = start
while (i <= end) {
yield i
Expand All @@ -66,10 +66,35 @@ export class List<T> {
} as any, this.length)
}

/**
* Delete the first N elements from a list.
* @param count
*/
public drop(count: number): List<T> {
const generator = this.generator() as any
return new List<T>(function* () {
let next = generator.next()
let n = 1

while (!next.done) {
if (n > count) yield next.value
n++
next = generator.next()
}
} as any, this.length - count)
}

/**
* Deletes the first element from a list.
* @param count
*/
tail(): List<T> {
return this.drop(1)
}

public scan<B>(fn: (acc: B, val: B) => B, seed: B): List<B> {
const generator = this.generator() as any
return new List(function* () {
// tslint:disable-next-line: no-let
let acc = seed
for (const value of generator) {
yield acc = fn(acc, value)
Expand Down Expand Up @@ -114,6 +139,25 @@ export class List<T> {
} as any, this.length + toAdd.length)
}

/**
* Make a new list containing just the first N elements from an existing list.
* @param count The number of elements to return.
*/
public take(count: number) {
const generator = this.generator() as any
return new List(function* () {

let next = generator.next()
let n = 0

while (!next.done && count > n) {
yield next.value
n++
next = generator.next()
}
} as any, this.length > count ? count : this.length)
}

/**
* Determines whether all elements of a sequence satisfy a condition.
*/
Expand All @@ -133,7 +177,7 @@ export class List<T> {
}

/**
* Determines whether a sequence contains any elements.
* Determines whether a sequence contains any elements matching the predicate.
* @param fn A function to test each element for a condition.
*/
public any(fn: (val: T) => boolean): boolean {
Expand All @@ -149,6 +193,34 @@ export class List<T> {
return newList.toArray().length >= 1
}

/**
* Determines whether a sequence contains any elements matching the predicate.
* @param fn A function to test each element for a condition.
* Aliased to any()
*/
public some(fn: (val: T) => boolean): boolean {
return this.any(fn)
}

/**
* Filters the elements of the list based on a specified type.
* @param type The type to filter the elements of the sequence on.
*/
public ofType(type: Function): List<T> {
return this.filter(a => a instanceof type)
}

// /**
// * Sorts the elements of a sequence in ascending order.
// */
// public orderBy<K extends keyof T>(prop?: T extends object ? K : never): List<T> {
// throw Error('Not Implemented')
// }

// public orderByDescending(): List<T> {
// throw Error('Not Implemented')
// }

/**
* Inverts the order of the elements in a sequence.
*/
Expand Down Expand Up @@ -196,7 +268,7 @@ export class List<T> {
return [...this as any] as T[]
}

/** Convert to standard array. Alias of toArray() */
/** Convert to standard array. Aliased to toArray() */
public toIterable(): Iterable<T> {
return this.toArray()
}
Expand Down