# Collection

The collection is an object an implementing ArrayLike and Iterable (opens new window) meaning it can be iterated with for... of or generators, has a .length property, and it can be indexed by numbers collection[0]. It implements all method available on the array (opens new window) in a compatible fashion. The collection is immutable unless the methods that are expected to mutate the collection: push, pop, unshift, shift, fill.

Instantiating a new collection is easy as:

import { Collection, collect } from '@upfrontjs/framework'

collect([1, 2, 3]);
// or
new Collection([1, 2, 3])
1
2
3
4
5

The constructor can take a single argument of an item or array of items or no argument.

WARNING

Note on extending the collection.

Given the collection is immutable it creates a new instance on method calls. If you're extending the collection, and your constructor takes a non-optional nth argument, the inherited methods will not work as it's impossible to tell what extra arguments might be needed.

# Methods

# first

The first method returns the first element of the collection. Optionally it takes a function to pick the first element by. If the collection is empty, it returns undefined.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.first(); // 1

collection.first(number => number > 2); // 3
1
2
3
4
5
6

# last

The last method returns the last element in the collection. Optionally it takes a function to pick the last element by. If the collection is empty, it returns undefined.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.last(); // 5
collection.first(number => number < 5); // 4
1
2
3
4
5

# random

The random method returns a random element from the collection. Optionally you may specify the number of random elements to pick. The argument's absolute value is used in case of negative integers.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.random(); // random element 
collection.random(2); // collection of 2 random elements
collection.random(collection.length); // return the whole collection
1
2
3
4
5
6

# isEmpty

The isEmpty method determines whether the collection is empty or not.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.isEmpty(); // false
(new Collection).isEmpty(); // true
1
2
3
4
5

# isNotEmpty

The isNotEmpty method determines whether the collection is not empty or is empty.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.isNotEmpty(); // true
(new Collection).isNotEmpty(); // false
1
2
3
4
5

# hasDuplicates

The hasDuplicates method determines if there are any duplicates in the collection based on deep equality.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.hasDuplicates(); // false
(new Collection([1, 1])).hasDuplicates(); // true
1
2
3
4
5

# unique

The unique method de-duplicates the collection based on deep equality. Optionally it takes one argument which is a string or function. On a function argument, the equality will be evaluated based on the function's return value. If the given argument is a string and all items in the collection are objects then if the object's key matching the string it will be based on the value's deep equality.

import { Collection } from '@upfrontjs/framework';

let collection = new Collection([1, 2, 1, 4, 5]);
collection.unique(); // Collection[1, 2, 4, 5]

collection = new Collection([
    { id: 1, name: 'name1' },
    { id: 2, name: 'name2' },
    { id: 3, name: 'name1' },
]);

collection.unique('name'); // Collection[{ id: 1, name: 'name1' },{ id: 2, name: 'name2' }]
collection.unique(obj => object.name); // Collection[{ id: 1, name: 'name1' },{ id: 2, name: 'name2' }]
1
2
3
4
5
6
7
8
9
10
11
12
13

# duplicates

The duplicates method returns only the duplicates from the collection. Optionally it takes one argument which is a string or function. On a function argument, the equality will be evaluated based on the function's return value. If the given argument is a string and all items in the collection are objects then if the object's key matching the string it will be based on the value's deep equality.

import { Collection } from '@upfrontjs/framework';

let collection = new Collection([1, 2, 1, 4, 5]);
collection.duplicates(); // Collection[1]

collection = new Collection([
    { id: 1, name: 'name1' },
    { id: 2, name: 'name2' },
    { id: 3, name: 'name1' }
]);

collection.duplicates('name'); // Collection[{ id: 1, name: 'name1' }]
collection.duplicates(obj => object.name); // Collection[{ id: 1, name: 'name1' }]
1
2
3
4
5
6
7
8
9
10
11
12
13

# delete

The delete method removes all elements that deep equal to the given value;

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.delete(3); // Collection[1, 2, 4, 5]
1
2
3
4

# nth

The nth method returns only every nth item in the collection.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.nth(2); // Collection[2, 4]
1
2
3
4

# withoutEmpty

The withoutEmpty method filters out every null and undefined values from the collection.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, null, 3, 4, 5, undefined]);
collection.withoutEmpty(); // Collection[1, 2, 3, 4, 5]
1
2
3
4

# pad

The pad method pads the collection to the given length with the given optional value. The value if it's a function, will be called. If the given length is a negative integer the value will be prepended.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3]);
collection.pad(5); // Collection[1, 2, 3, undefined, undefined]
collection.pad(1); // Collection[1, 2, 3]
collection.pad(-5); // Collection[undefined, undefined, 1, 2, 3]
collection.pad(4, 'value'); // Collection[1, 2, 3, 'value']
collection.pad(4, () => 'return value'); // Collection[1, 2, 3, 'return value']
1
2
3
4
5
6
7
8

# union

The union method joins one or more iterables without overlapping values based on deep equality.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.union(1, [4, 6], new Collection(7)); // Collection[1, 2, 3, 4, 5, 6, 7]
1
2
3
4

# diff

The diff method returns the difference between the collection and the given item or array/collection based on deep equality.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.diff([2, 3, 4, 5, 6]); // Collection[1, 6]
collection.diff(1); // Collection[2, 3, 4, 5]
1
2
3
4
5

# intersect

The intersect method returns the values that are present in both the collection, and the given value.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.intersect(1); // Colection[1]
collection.intersect(new Collection([3, 4, 5, 6])); // Colection[3, 4, 5]
1
2
3
4
5

# chunk

The chunk method returns a collection of collections with the given size.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.chunk(2); // Collection[Collection[1, 2], Collection[3, 4], Collection[5]]
collection.chunk(5); // Collection[Collection[1, 2, 3, 4, 5]]
1
2
3
4
5

# when

The when method executes the given method if the first argument evaluates to true. The method has to return the collection.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.when(true, collectionCopy => collectionCopy.nth(2)); // Collection[2, 4]
collection.when(() => false, collectionCopy => collectionCopy.nth(2)); // Collection[1, 2, 3, 4, 5]
1
2
3
4
5

# unless

The unless method executes the given method if the first argument evaluates to false. The method has to return the collection.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.unless(false, collectionCopy => collectionCopy.nth(2)); // Collection[2, 4]
collection.unless(() => true, collectionCopy => collectionCopy.nth(2)); // Collection[1, 2, 3, 4, 5]
1
2
3
4
5

# whenEmpty

The whenEmpty method executes the given method if the collection is empty.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
let count = 0;
collection.whenEmpty(collectionCopy => count++);
count; // 0
(new Collection).whenEmpty(collectionCopy => count++);
count; // 1
1
2
3
4
5
6
7
8

# whenNotEmpty

The whenNotEmpty method executes the given method when the collection is not empty.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
let count = 0;
collection.whenNotEmpty(collectionCopy => count++);
count; // 1
(new Collection).whenNotEmpty(collectionCopy => count++);
count; // 1
1
2
3
4
5
6
7
8

# take

The take method returns given number of items. On negative integer, it returns items from the end first.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.take(2); // Collection[1, 2]
collection.take(-2); // Collection[4, 5]
1
2
3
4
5

# takeUntil

The takeUntil method takes items from the collection until the given function called with the item returns false.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.takeUntil(item => item >= 4); // Collection[1, 2, 3]
1
2
3
4

# takeWhile

The takeWhile method takes items from the collection until the given function called with the item returns true.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.takeWhile(item => item < 4); // Collection[1, 2, 3]
1
2
3
4

# skip

The skip method skips the given number of items in the collection.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.skip(3); // Collection[4, 5]
1
2
3
4

# skipUntil

The skipUntil method skips items until the given function returns false.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.skipUntil(item => item > 2); // Collection[3, 4, 5]
1
2
3
4

# skipWhile

The skipWhile method skips items until the given function returns true.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.skipWhile(item => item <= 2); // Collection[3, 4, 5]
1
2
3
4

# pluck

When all items in the collections are objects then you may use to The pluck method to get certain attributes in a collection or multiple attributes in a collection of objects

import { Collection } from '@upfrontjs/framework';

const collection = new Collection(
    { id: 1, name: 'name1', email: 'test1@email.com' },
    { id: 2, name: 'name2', email: 'test2@email.com' },
    { id: 3, name: 'name3', email: 'test3@email.com' },
);
collection.pluck('name'); // Collection['name1', 'name2', 'name3']
collection.pluck(['id', 'name']); // Collection[{ id: 1, name: 'name1' }, { id: 2, name: 'name2' }, { id: 3, name: 'name3' }]
1
2
3
4
5
6
7
8
9

# tap

The tap method executes the given function with the collection without changing the collection.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.tap(collectionCopy => collection.take(2)); // Collection([1, 2, 3, 4, 5])
1
2
3
4

# pipe

The pipe method executes the given function with the collection. The function must return the collection.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.pipe(collectionCopy => collection.take(2)); // Collection([1, 2])
1
2
3
4

# dump

The dump method is a debugging function which prints out the collection in its current state to the console. It is chainable. Optionally it can take a message argument.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.dump(); // logged: '10:37:05 - All items: 1,2,3,4,5'
collection.dump('test'); // logged: '10:37:05 (test) - All items: 1,2,3,4,5'
collection.dump().take(2); // Collection[1, 2]
1
2
3
4
5
6

# toArray

The toArray method creates an array (opens new window) from the collection.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.toArray(); // [1, 2, 3, 4, 5]
1
2
3
4

# toJson

The toJson method returns the JSON representation of the collection.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.toJson(); // '{"0":1,"1":2,"2":3,"3":4,"4":5,"length":5}'
1
2
3
4

# isCollection

The isCollection static method is used to evaluate whether the given value is a collection.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
Collection.isCollection(collection); // true
Collection.isCollection(1); // false
1
2
3
4
5

# times

The times static method is used to create a new collection consisting of the given value with the given number of times. A function may also be passed which will be called with the current iteration (iteration starting at 1).

import { Collection } from '@upfrontjs/framework';

Collection.times(3, 'value'); // Collection['value', 'value', 'value']
Collection.times(3, i => i); // Collection[1, 2, 3]
1
2
3
4

# forEach

The forEach works the same way as the base forEach (opens new window), except it is chainable.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2, 3, 4, 5]);
collection.forEach(number => console.log(number)).take(2); // Collection([1, 2])
1
2
3
4

# includes

The includes works the same way as the base includes (opens new window), except it evaluates based on deep equality.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([{ id: 1 }, { id: 2 }]);
collection.include({ id: 2 }); // true
collection.include(2); // false
1
2
3
4
5

# join

The join method works the same way the base join (opens new window), except when using a collection of object the first argument is can be a property key or getter function receiving the object.

import { Collection } from '@upfrontjs/framework';

const collection = new Collection([1, 2]);
collection.join('-'); // '1-2'

const objectCollection = new Collection([{ id: 1 }, { id: 2 }]);
objectCollection.join('id', '-'); // '1-2'
objectCollection.join(obj => obj.id + 1); // '2,3'
1
2
3
4
5
6
7
8

# sum

The sum method returns the summative the collection numbers while casting strings to numbers if possible otherwise throws an error. Optionally it takes a string for the property key or getter function receiving the item to return a single value.

import { Collection } from '@upfrontjs/framework';

let collection = new Collection([1, 2]);

collection.sum(); // 3

collection = new Collection(['3', '4']);
collection.sum(); // 7

collection = new Collection([{ id: 1 }, { id: 2 }]);
collection.sum('id'); // 3
collection.sum(obj => obj.id); // 3
1
2
3
4
5
6
7
8
9
10
11
12

# min

The min method returns the lowest number from the collection while casting strings to numbers if possible otherwise throws an error. Optionally it takes a string for the property key or getter function receiving the item to return a single value.

import { Collection } from '@upfrontjs/framework';

let collection = new Collection([1, 2]);

collection.min(); // 1

collection = new Collection(['3', '4']);
collection.min(); // 3

collection = new Collection([{ id: 1 }, { id: 2 }]);
collection.min('id'); // 1
collection.min(obj => obj.id); // 1
1
2
3
4
5
6
7
8
9
10
11
12

# max

The max method returns the highest number from the collection while casting strings to numbers if possible otherwise throws an error. Optionally it takes a string for the property key or getter function receiving the item to return a single value.

import { Collection } from '@upfrontjs/framework';

let collection = new Collection([1, 2]);

collection.max(); // 2

collection = new Collection(['3', '4']);
collection.max(); // 4

collection = new Collection([{ id: 1 }, { id: 2 }]);
collection.max('id'); // 2
collection.max(obj => obj.id); // 2
1
2
3
4
5
6
7
8
9
10
11
12

# average

The average method returns the average of the number from the collection while casting strings to numbers if possible otherwise throws an error. Optionally it takes a string for the property key or getter function receiving the item to return a single value.

import { Collection } from '@upfrontjs/framework';

let collection = new Collection([1, 2]);

collection.average(); // 1.5

collection = new Collection(['3', '4']);
collection.average(); // 3.5

collection = new Collection([{ id: 1 }, { id: 2 }]);
collection.average('id'); // 1.5
collection.average(obj => obj.id); // 1.5
1
2
3
4
5
6
7
8
9
10
11
12