Skip to the content
OrielDocs
0.1.0-alpha.10GitHub

Digging deeper

Collections

A collection wraps a list of items with Laravel's collection methods: filter it, map it, group it, sort it and sum it, one chained call after another.

Introduction#

Collection wraps an array. Here collect() makes a collection of the array, uppercases each name, and drops the empty one:

const collection = collect(['Taylor', 'Abigail', null])  .map((name) => name?.toUpperCase())  .reject((name) => !name)collection.all()// ['TAYLOR', 'ABIGAIL']

Methods that change the items, such as map() and reject(), return a new collection and leave the one you called them on as it was. A few methods change the collection itself, and say so: push(), pop(), put(), transform() and the others listed under Changing a collection in place.

Collections are iterable, so for...of and the spread operator work on them, and JSON.stringify() writes their items as an array. Your queries return collections too: a query's models come back in an EloquentCollection, which has every method here and a few for models, covered on Eloquent collections.

Creating collections#

collect() makes a collection from an array, or from anything iterable, such as a Set:

const collection = collect([1, 2, 3])

Collection.make() does the same, and times(), range(), wrap() and fromJson() build one in other ways. A collection's type comes from its items: collect([1, 2, 3]) is a Collection<number>, and the callbacks you give its methods are typed with it.

A collection is a list#

A Laravel collection is a PHP array, whose items have keys: numbers, as in a list, or strings, as in a dictionary. An Oriel collection is a list. Its items are always numbered from 0, in order, with no gaps:

  • methods that keep some of the items, such as filter(), unique() and sortBy(), number them again from 0. You never need values() to reset the keys, as you do in Laravel;
  • Laravel's methods that take a key take an index: get(1), has(0), only(0, 2), except(1), put(1, value), pull(1), forget(1), replace({ 1: value }) and splice(). search() returns an index, and keys() the indexes;
  • removing an item, with forget() or pull(), moves the later items up;
  • put() and replace() with an index past the end add the item at the end. A negative or fractional index throws a RangeError: "Invalid collection index [-1].";
  • methods that build a dictionary return a plain object, not a collection: keyBy(), groupBy(), mapWithKeys(), countBy(), flip(), combine(), mapToDictionary() and mapToGroups().
const collection = collect(['a', 'b', 'c'])collection.forget(0)collection.all()// ['b', 'c']collection.get(0)// 'b'

Laravel's methods that only make sense for keys aren't in Oriel; Methods left out lists them.

Strict and loose comparisons#

Laravel compares values loosely in most methods, so the string '1' equals the number 1, and offers a strict twin for some of them. Oriel compares loosely, with JavaScript's ==, only in these:

  • where(key, value), firstWhere(key, value), every(key, value), sole(key, value), firstOrFail(key, value), and every form that takes an operator, such as where('price', '>', 100) and contains('price', '=', 100);
  • search(), before() and after(), unless you pass true as their last argument;
  • duplicates(), whose strict twin is duplicatesStrict().

Everything else compares strictly, with ===: contains(value), contains(key, value), some() and doesntContain() with a value, unique(), whereIn(), whereNotIn(), diff(), intersect(), takeUntil() and the others. Their Strict names, such as containsStrict() and uniqueStrict(), are the same methods under Laravel's other name.

const products = collect([{ product: 'Desk', price: 200 }])products.where('price', '200').count()// 1products.contains('price', '200')// false

Keys and callbacks#

Many methods read a value from each item: give them the name of a property, as sortBy('price'), or a function that returns the value, as sortBy((product) => product.price). TypeScript checks a name against the items' type. A callback receives the item and its index.

Where Laravel's callback returns null to mean "no value", Oriel's methods return undefined: first() on an empty collection, avg() with no numbers, get() past the end.

Extending collections#

Laravel adds methods to every collection with Collection::macro(). Oriel has no macros: methods added while your app runs are invisible to TypeScript. Extend Collection instead:

app/Support/ProductCollection.ts
import { Collection } from '@orieljs/framework'interface Product {  name: string  price: number}export class ProductCollection extends Collection<Product> {  total(): number {    return this.sum('price')  }}

Methods that keep the same kind of items, such as filter(), sortBy(), where() and take(), return your class, so new ProductCollection(products).where('price', '>', 100).total() works. Methods that make other items, such as map() and pluck(), return a plain Collection. A subclass whose constructor takes other arguments must override the protected newInstance(items), which the methods use to make their result.

Available methods#

Each method below has a short entry, in alphabetical order. Static methods, called on Collection, are marked so.

add, after, all, average, avg, before, chunk, chunkWhile, collapse, collect, combine, concat, contains, containsOneItem, containsStrict, count, countBy, crossJoin, diff, diffUsing, doesntContain, doesntContainStrict, dump, duplicates, duplicatesStrict, each, eachSpread, empty, ensure, every, except, filter, first, firstOrFail, firstWhere, flatMap, flatten, flip, forget, forPage, fromJson, get, groupBy, has, hasAny, implode, intersect, intersectUsing, isEmpty, isNotEmpty, join, keyBy, keys, last, lazy, make, map, mapInto, mapSpread, mapToDictionary, mapToGroups, mapWithKeys, max, median, merge, min, mode, multiply, nth, only, pad, partition, percentage, pipe, pipeInto, pipeThrough, pluck, pop, prepend, pull, push, put, random, range, reduce, reduceSpread, reject, replace, reverse, search, select, shift, shuffle, skip, skipUntil, skipWhile, slice, sliding, sole, some, sort, sortBy, sortByDesc, sortDesc, splice, split, splitIn, sum, take, takeUntil, takeWhile, tap, times, toArray, toJson, transform, unique, uniqueStrict, unless, unlessEmpty, unlessNotEmpty, unshift, unwrap, value, values, when, whenEmpty, whenNotEmpty, where, whereBetween, whereIn, whereInstanceOf, whereInStrict, whereNotBetween, whereNotIn, whereNotInStrict, whereNotNull, whereNull, whereStrict, wrap, zip

Changing a collection in place#

These methods change the collection you call them on: add(), forget(), pop(), prepend(), pull(), push(), put(), shift(), splice(), transform() and unshift(). Every other method leaves it as it is.

Methods left out#

Laravel's methods for a collection's keys aren't in Oriel, because a collection is a list, whose keys are its indexes: diffAssoc(), diffAssocUsing(), diffKeys(), intersectAssoc(), intersectAssocUsing(), intersectByKeys(), union(), mergeRecursive(), replaceRecursive(), sortKeys(), sortKeysDesc(), sortKeysUsing(), collapseWithKeys(), dot() and undot(). For keyed data, use an object or a Map, or build one with keyBy() or mapWithKeys().

These aren't in Oriel either:

  • macro(): see Extending collections;
  • dd(): JavaScript can't stop the program where you call it. dump() logs the items;
  • hasMany(): compare count() with 1;
  • hasSole(): Oriel names it containsOneItem();
  • higher order messages, such as $users->each->markAsVip(): pass a function, users.each((user) => user.markAsVip());
  • dot notation in keys, such as pluck('user.name'): give the method a function where it takes one, or map() the value out first: map((item) => item.user.name).

Method listing#

add()#

add() adds one item at the end of the collection, changing it, and returns the collection:

const collection = collect([1, 2])collection.add(3)collection.all()// [1, 2, 3]

after()#

after() returns the item after the given one, or undefined when the item is the last one or isn't there:

const collection = collect([1, 2, 3, 4, 5])collection.after(3)// 4collection.after(5)// undefined

It compares loosely, so '4' finds 4. Pass true to compare strictly:

collect<number | string>([2, 4, 6, 8]).after('4', true)// undefined

It also takes a function, and returns the item after the first one that passes it:

collect([2, 4, 6, 8]).after((item) => item > 5)// 8

all()#

all() returns the items, as a new array:

collect([1, 2, 3]).all()// [1, 2, 3]

average()#

Another name for avg().

avg()#

avg() returns the average of the items, or of a key's values:

collect([{ foo: 10 }, { foo: 10 }, { foo: 20 }, { foo: 40 }]).avg('foo')// 20collect([1, 1, 2, 4]).avg()// 2

Only numbers count: a string such as '1', null and other values are left out, and a collection with no numbers gives undefined. Laravel counts numeric strings, and gives null.

before()#

before() is the opposite of after(): it returns the item before the given one, or undefined:

const collection = collect([1, 2, 3, 4, 5])collection.before(3)// 2collection.before(1)// undefinedcollect([2, 4, 6, 8]).before((item) => item > 5)// 4

chunk()#

chunk() splits the collection into collections of the given size, the last one smaller when the items run out:

const chunks = collect([1, 2, 3, 4, 5, 6, 7]).chunk(4)chunks.toArray()// [[1, 2, 3, 4], [5, 6, 7]]

chunkWhile()#

chunkWhile() splits the collection where the callback returns false. The callback receives the item, its index and the chunk so far:

const chunks = collect('AABBCCCD'.split('')).chunkWhile((value, index, chunk) => value === chunk.last())chunks.toArray()// [['A', 'A'], ['B', 'B'], ['C', 'C', 'C'], ['D']]

collapse()#

collapse() merges a collection of arrays, or of collections, into one flat collection. Other items are dropped:

const collapsed = collect([  [1, 2, 3],  [4, 5, 6],  [7, 8, 9],]).collapse()collapsed.all()// [1, 2, 3, 4, 5, 6, 7, 8, 9]

collect()#

collect() returns a plain Collection with the same items. On a subclass, such as the EloquentCollection your queries return, it gives you a base collection:

const collection = collect([1, 2, 3]).collect()

combine()#

combine() uses the items as keys for the values you give, and returns a plain object. Both must have the same number of items, or it throws a RangeError:

collect(['name', 'age']).combine(['George', 29])// { name: 'George', age: 29 }

concat()#

concat() returns the items followed by the ones you give:

const concatenated = collect(['John Doe']).concat(['Jane Doe']).concat(['Johnny Doe'])concatenated.all()// ['John Doe', 'Jane Doe', 'Johnny Doe']

contains()#

contains() tells you whether the collection has an item. Given a function, it tells you whether an item passes it:

collect([1, 2, 3, 4, 5]).contains((value) => value > 5)// false

Given a value, it tells you whether an item is that value:

const collection = collect(['Desk', 'Chair'])collection.contains('Desk')// truecollection.contains('New York')// false

Given a key and a value, it tells you whether an item has that value:

const collection = collect([  { product: 'Desk', price: 200 },  { product: 'Chair', price: 100 },])collection.contains('product', 'Bookcase')// false

A value, and a key and a value, are compared strictly, where Laravel compares them loosely: collect([1, 2]).contains('1') is false. Given a key, an operator and a value, it compares as where() does, loosely: collection.contains('price', '>', 150).

containsOneItem()#

containsOneItem() tells you whether the collection has exactly one item, or exactly one that passes the callback. It is Laravel's hasSole():

collect([]).containsOneItem()// falsecollect(['1']).containsOneItem()// truecollect([1, 2, 3]).containsOneItem((item) => item === 2)// true

containsStrict()#

The same as contains(), which already compares strictly.

count()#

count() returns the number of items:

collect([1, 2, 3, 4]).count()// 4

countBy()#

countBy() counts how many times each value appears, and returns a plain object:

collect([1, 2, 2, 2, 3]).countBy()// { 1: 1, 2: 3, 3: 1 }

Given a key or a function, it counts what that gives for each item:

collect(['alice@gmail.com', 'bob@yahoo.com', 'carlos@gmail.com']).countBy((email) => email.split('@')[1])// { 'gmail.com': 2, 'yahoo.com': 1 }

crossJoin()#

crossJoin() returns every combination of the items with the items of the lists you give:

collect([1, 2]).crossJoin(['a', 'b']).all()// [[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']]collect([1, 2]).crossJoin(['a', 'b'], ['I', 'II']).all()// [[1, 'a', 'I'], [1, 'a', 'II'], [1, 'b', 'I'], [1, 'b', 'II'],//  [2, 'a', 'I'], [2, 'a', 'II'], [2, 'b', 'I'], [2, 'b', 'II']]

diff()#

diff() returns the items that aren't in the list you give, compared strictly:

const diff = collect([1, 2, 3, 4, 5]).diff([2, 4, 6, 8])diff.all()// [1, 3, 5]

Laravel compares the items as strings, so 1 and '1' match there and not here.

diffUsing()#

diffUsing() is diff() with your own comparison: a function that returns 0 for two items that are the same:

const diff = collect(['a', 'B', 'c']).diffUsing(['A', 'b'], (a, b) => a.toLowerCase().localeCompare(b.toLowerCase()))diff.all()// ['c']

doesntContain()#

doesntContain() is the opposite of contains(), and takes the same arguments, compared the same way:

collect([1, 2, 3, 4, 5]).doesntContain((value) => value < 5)// falsecollect(['Desk', 'Chair']).doesntContain('Table')// truecollect([{ product: 'Desk', price: 200 }]).doesntContain('product', 'Bookcase')// true

doesntContainStrict()#

The same as doesntContain(), which already compares strictly.

dump()#

dump() logs the items with console.log(), and any values you pass after them, and returns the collection, so you can call it in the middle of a chain:

collect(['John Doe', 'Jane Doe']).dump()

duplicates()#

duplicates() returns the values that appear more than once, each time after the first, compared loosely:

collect(['a', 'b', 'a', 'c', 'b']).duplicates().all()// ['a', 'b']

Given a key or a function, it looks for repeated values of it:

const employees = collect([  { email: 'abigail@example.com', position: 'Developer' },  { email: 'james@example.com', position: 'Designer' },  { email: 'victoria@example.com', position: 'Developer' },])employees.duplicates('position').all()// ['Developer']

Laravel's result keeps each duplicate's position as its key; Oriel's is a list of the values.

duplicatesStrict()#

duplicates(), compared strictly: collect([1, '1']).duplicatesStrict() is empty.

each()#

each() calls the function with each item and its index. Return false to stop:

collect([1, 2, 3, 4]).each((item) => {  if (item > 2) {    return false  }  console.log(item)})

eachSpread()#

eachSpread() is each() for a collection of lists: each list's items are the function's arguments, followed by the index:

collect([  ['John Doe', 35],  ['Jane Doe', 33],]).eachSpread((name, age) => {  // ...})

empty()#

Static. Collection.empty() returns a collection with no items.

ensure()#

ensure() checks that every item is of a type, or of one of a list of types, and throws a TypeError when one isn't: "Collection should only include [number] items, but 'string' found at position 1.". A type is a class, or one of JavaScript's type names: 'string', 'number', 'bigint', 'boolean', 'symbol', 'undefined', 'function', 'object', and 'null' and 'array'. It returns the collection, typed with those items:

const users = items.ensure(User)const numbers = items.ensure(['number', 'string'])

Laravel's type names are PHP's ('int', 'float', 'bool'); Oriel's are JavaScript's. ensure() doesn't stop other items from being added later.

every()#

every() tells you whether every item passes the function:

collect([1, 2, 3, 4]).every((value) => value > 2)// false

An empty collection gives true. Given a key, a key and a value, or a key, an operator and a value, it checks each item as where() does, loosely.

except()#

except() returns every item but those at the indexes you give. Laravel's takes keys:

collect(['a', 'b', 'c', 'd']).except(0, 2).all()// ['b', 'd']

filter()#

filter() keeps the items that pass the function:

const filtered = collect([1, 2, 3, 4]).filter((value) => value > 2)filtered.all()// [3, 4]

Without a function, it keeps the items that are truthy in JavaScript, so an empty array stays, where PHP drops it:

collect([1, 2, 3, null, false, '', 0, []]).filter().all()// [1, 2, 3, []]

The result is numbered from 0. For the opposite, see reject().

first()#

first() returns the first item that passes the function, or the first item when you give none:

collect([1, 2, 3, 4]).first((value) => value > 2)// 3collect([1, 2, 3, 4]).first()// 1

When no item passes, it returns undefined, or the default you give as its second argument: collect([1]).first((value) => value > 5, 'none') is 'none'.

firstOrFail()#

firstOrFail() is first(), but throws an ItemNotFoundError, "Item not found.", when no item passes:

collect([1, 2, 3, 4]).firstOrFail((value) => value > 5)// throws ItemNotFoundError

It also takes a key and a value, or a key, an operator and a value, compared as where() does.

firstWhere()#

firstWhere() returns the first item whose key has the value, compared loosely, or undefined:

const users = collect([  { name: 'Regena', age: null },  { name: 'Linda', age: 14 },  { name: 'Diego', age: 23 },  { name: 'Linda', age: 84 },])users.firstWhere('name', 'Linda')// { name: 'Linda', age: 14 }

It takes an operator too, and with a key alone it finds the first item whose key is truthy:

users.firstWhere('age', '>=', 18)// { name: 'Diego', age: 23 }users.firstWhere('age')// { name: 'Linda', age: 14 }

flatMap()#

flatMap() maps each item, and flattens the results one level:

const collection = collect([{ name: 'Sally' }, { school: 'Arkansas' }, { age: 28 }])const flattened = collection.flatMap((values) => Object.values(values).map((value) => String(value).toUpperCase()))flattened.all()// ['SALLY', 'ARKANSAS', '28']

flatten()#

flatten() opens up nested arrays and collections, to every depth:

const flattened = collect([  ['PHP', 'JavaScript'],  [['Ruby'], 'Go'],]).flatten()flattened.all()// ['PHP', 'JavaScript', 'Ruby', 'Go']

Give it a depth to open fewer levels:

collection.flatten(1).all()// ['PHP', 'JavaScript', ['Ruby'], 'Go']

Plain objects stay as they are. Laravel flattens an associative array's values too.

flip()#

flip() returns a plain object with each item as a key, and its index as the value:

collect(['taylor', 'laravel']).flip()// { taylor: 0, laravel: 1 }

forget()#

forget() removes the items at the indexes you give, changing the collection, and the later items move up:

const collection = collect(['a', 'b', 'c'])collection.forget(1)collection.all()// ['a', 'c']

forPage()#

forPage() returns the items of one page, given the page number and the number of items per page:

const chunk = collect([1, 2, 3, 4, 5, 6, 7, 8, 9]).forPage(2, 3)chunk.all()// [4, 5, 6]

fromJson()#

Static. Collection.fromJson() decodes a JSON string: an array gives its items, null an empty collection, and any other value a collection of that one value:

Collection.fromJson('[1, 2, 3]').all()// [1, 2, 3]Collection.fromJson('{"name": "Taylor"}').all()// [{ name: 'Taylor' }]

Laravel makes a JSON object into a collection keyed by its properties.

get()#

get() returns the item at an index, or undefined. Laravel's takes a key:

const collection = collect(['taylor', 'abigail'])collection.get(1)// 'abigail'

A second argument is the default, returned when there is no item at the index. A function default is called:

const collection = collect(['taylor'])collection.get(5, 'default')// 'default'collection.get(5, () => 'computed')// 'computed'

groupBy()#

groupBy() groups the items by a key's value, and returns a plain object of collections:

const collection = collect([  { account_id: 'account-x10', product: 'Chair' },  { account_id: 'account-x10', product: 'Bookcase' },  { account_id: 'account-x11', product: 'Desk' },])const grouped = collection.groupBy('account_id')// {//   'account-x10': [{ account_id: 'account-x10', product: 'Chair' }, { account_id: 'account-x10', product: 'Bookcase' }],//   'account-x11': [{ account_id: 'account-x11', product: 'Desk' }],// }grouped['account-x11']?.count()// 1

Given a function, it groups by what the function returns:

const grouped = collection.groupBy((item) => item.account_id.slice(-3))// { x10: [...], x11: [...] }

Laravel's groupBy() also takes several keys, for nested groups, and can keep the items' keys. Oriel's takes one key or function: group each group again for nested groups.

has()#

has() tells you whether there is an item at every index you give. Laravel's takes keys:

const collection = collect(['Desk', 'Chair', 'Bookcase'])collection.has(1)// truecollection.has(0, 5)// false

hasAny()#

hasAny() tells you whether there is an item at any of the indexes you give:

collect(['Desk']).hasAny(0, 5)// true

implode()#

implode() joins the items into a string, with the glue between them:

collect([1, 2, 3, 4, 5]).implode('-')// '1-2-3-4-5'

For items that are objects, give the key first, or a function:

const collection = collect([  { account_id: 1, product: 'Desk' },  { account_id: 2, product: 'Chair' },])collection.implode('product', ', ')// 'Desk, Chair'collection.implode((item) => item.product.toUpperCase(), ', ')// 'DESK, CHAIR'

intersect()#

intersect() keeps the items that are also in the list you give, compared strictly:

const intersect = collect(['Desk', 'Sofa', 'Chair']).intersect(['Desk', 'Chair', 'Bookcase'])intersect.all()// ['Desk', 'Chair']

intersectUsing()#

intersectUsing() is intersect() with your own comparison, a function that returns 0 for two items that are the same:

const intersect = collect(['Desk', 'Sofa', 'Chair']).intersectUsing(['desk', 'chair', 'bookcase'], (a, b) =>  a.toLowerCase().localeCompare(b.toLowerCase()),)intersect.all()// ['Desk', 'Chair']

isEmpty()#

isEmpty() tells you whether the collection has no items:

collect([]).isEmpty()// true

isNotEmpty()#

isNotEmpty() tells you whether the collection has items:

collect([]).isNotEmpty()// false

join()#

join() joins the items into a string, with the glue between them, and another glue before the last one if you give it:

collect(['a', 'b', 'c']).join(', ')// 'a, b, c'collect(['a', 'b', 'c']).join(', ', ', and ')// 'a, b, and c'collect(['a', 'b']).join(', ', ' and ')// 'a and b'collect(['a']).join(', ', ' and ')// 'a'

keyBy()#

keyBy() returns a plain object of the items, under a key's value. When two items have the same value, the last one stays:

const collection = collect([  { product_id: 'prod-100', name: 'Desk' },  { product_id: 'prod-200', name: 'Chair' },])collection.keyBy('product_id')// {//   'prod-100': { product_id: 'prod-100', name: 'Desk' },//   'prod-200': { product_id: 'prod-200', name: 'Chair' },// }

It takes a function too: collection.keyBy((item) => item.product_id.toUpperCase()).

keys()#

keys() returns the indexes, from 0:

collect(['a', 'b', 'c']).keys().all()// [0, 1, 2]

last()#

last() returns the last item that passes the function, or the last item when you give none, or undefined:

collect([1, 2, 3, 4]).last((value) => value < 3)// 2collect([1, 2, 3, 4]).last()// 4

Like first(), it takes a default as its second argument.

lazy()#

lazy() returns a lazy collection of a copy of the items, so later changes to this collection don't reach it:

const lazyCollection = collect([1, 2, 3, 4]).lazy()const evens = await lazyCollection.filter((value) => value % 2 === 0).collect()

make()#

Static. Collection.make() makes a collection, as collect() does.

map()#

map() calls the function with each item and its index, and returns a collection of the results:

const multiplied = collect([1, 2, 3, 4, 5]).map((item) => item * 2)multiplied.all()// [2, 4, 6, 8, 10]

To change the collection itself, use transform().

mapInto()#

mapInto() makes an instance of a class for each item, with new and the item, then the index:

class Currency {  constructor(public code: string) {}}const currencies = collect(['USD', 'EUR', 'GBP']).mapInto(Currency)currencies.all()// [Currency { code: 'USD' }, Currency { code: 'EUR' }, Currency { code: 'GBP' }]

mapSpread()#

mapSpread() is map() for a collection of lists: each list's items are the function's arguments, followed by the index:

const sequence = collect([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])  .chunk(2)  .mapSpread((even, odd) => even + odd)sequence.all()// [1, 5, 9, 13, 17]

mapToDictionary()#

mapToDictionary() is mapToGroups() with arrays for the groups in place of collections:

const collection = collect([  { name: 'John Doe', department: 'Sales' },  { name: 'Jane Doe', department: 'Sales' },])collection.mapToDictionary((item) => [item.department, item.name])// { Sales: ['John Doe', 'Jane Doe'] }

mapToGroups()#

mapToGroups() groups the items by the function's results. The function returns a [key, value] pair, and the result is a plain object of collections:

const collection = collect([  { name: 'John Doe', department: 'Sales' },  { name: 'Jane Doe', department: 'Sales' },  { name: 'Johnny Doe', department: 'Marketing' },])const grouped = collection.mapToGroups((item) => [item.department, item.name])// { Sales: ['John Doe', 'Jane Doe'], Marketing: ['Johnny Doe'] }grouped.Sales?.all()// ['John Doe', 'Jane Doe']

Laravel's function returns a one-entry array, [$key => $value].

mapWithKeys()#

mapWithKeys() builds a plain object from the function's results, each a [key, value] pair:

const collection = collect([  { name: 'John', department: 'Sales', email: 'john@example.com' },  { name: 'Jane', department: 'Marketing', email: 'jane@example.com' },])collection.mapWithKeys((item) => [item.email, item.name])// { 'john@example.com': 'John', 'jane@example.com': 'Jane' }

Laravel's function returns a one-entry array, and the result is a collection.

max()#

max() returns the largest number among the items, or a key's values, or undefined when there is none:

collect([{ foo: 10 }, { foo: 20 }]).max('foo')// 20collect([1, 2, 3, 4, 5]).max()// 5

Only numbers count. Laravel's max() compares other values too.

median()#

median() returns the middle number, or the average of the two middle ones, of the items or a key's values:

collect([{ foo: 10 }, { foo: 10 }, { foo: 20 }, { foo: 40 }]).median('foo')// 15collect([1, 1, 2, 4]).median()// 1.5

Only numbers count, and a collection with none gives undefined.

merge()#

merge() returns the items followed by the ones you give, as concat() does:

const merged = collect(['Desk', 'Chair']).merge(['Bookcase', 'Door'])merged.all()// ['Desk', 'Chair', 'Bookcase', 'Door']

Laravel's merge() overwrites the items of string keys; a list has none.

min()#

min() returns the smallest number among the items, or a key's values, or undefined when there is none:

collect([{ foo: 10 }, { foo: 20 }]).min('foo')// 10collect([1, 2, 3, 4, 5]).min()// 1

mode()#

mode() returns the most frequent values, in an array, in the order they first appear, or undefined for an empty collection:

collect([{ foo: 10 }, { foo: 10 }, { foo: 20 }, { foo: 40 }]).mode('foo')// [10]collect([1, 1, 2, 4]).mode()// [1]collect([1, 1, 2, 2]).mode()// [1, 2]

multiply()#

multiply() repeats the items the given number of times:

const users = collect([  { name: 'User #1', email: 'user1@example.com' },  { name: 'User #2', email: 'user2@example.com' },]).multiply(3)users.count()// 6

nth()#

nth() returns every nth item, from the first, or from the offset you give:

const collection = collect(['a', 'b', 'c', 'd', 'e', 'f'])collection.nth(4).all()// ['a', 'e']collection.nth(4, 1).all()// ['b', 'f']

only()#

only() returns the items at the indexes you give, in the collection's order. Laravel's takes keys:

collect(['a', 'b', 'c', 'd']).only(0, 2).all()// ['a', 'c']

pad()#

pad() fills the collection with the value up to the given size. A negative size pads at the start, and a size no larger than the collection changes nothing:

const collection = collect(['A', 'B', 'C'])collection.pad(5, 0).all()// ['A', 'B', 'C', 0, 0]collection.pad(-5, 0).all()// [0, 0, 'A', 'B', 'C']

partition()#

partition() returns two collections: the items that pass the function, and the ones that don't:

const [underThree, equalOrAboveThree] = collect([1, 2, 3, 4, 5, 6]).partition((item) => item < 3)underThree.all()// [1, 2]equalOrAboveThree.all()// [3, 4, 5, 6]

percentage()#

percentage() returns the share of the items that pass the function, as a percentage, rounded to two decimal places or the number you give, or undefined for an empty collection:

const collection = collect([1, 1, 2, 2, 2, 3])collection.percentage((value) => value === 1)// 33.33collection.percentage((value) => value === 1, 3)// 33.333

pipe()#

pipe() passes the collection to the function, and returns what it returns:

collect([1, 2, 3]).pipe((collection) => collection.sum())// 6

pipeInto()#

pipeInto() makes an instance of a class with the collection, new and the collection:

class ResourceCollection {  constructor(public collection: Collection<number>) {}}const resource = collect([1, 2, 3]).pipeInto(ResourceCollection)resource.collection.all()// [1, 2, 3]

pipeThrough()#

pipeThrough() passes the collection to the first function, its result to the next, and so on, and returns the last result:

const result = collect([1, 2, 3]).pipeThrough([  (collection) => collection.merge([4, 5]),  (collection) => collection.sum(),])// 15

pluck()#

pluck() returns a key's values:

const collection = collect([  { product_id: 'prod-100', name: 'Desk' },  { product_id: 'prod-200', name: 'Chair' },])collection.pluck('name').all()// ['Desk', 'Chair']

Laravel's pluck() also takes a second key, for the result's keys, and dot notation for nested values. Oriel's takes one key: for a dictionary of values, use mapWithKeys(), and for a nested value, map().

pop()#

pop() removes the last item and returns it, changing the collection:

const collection = collect([1, 2, 3, 4, 5])collection.pop()// 5collection.all()// [1, 2, 3, 4]

Given a number, it removes that many from the end and returns them in a collection, the last first:

collect([1, 2, 3, 4, 5]).pop(3).all()// [5, 4, 3]

Laravel's pop(1) returns the item; Oriel's returns a collection whenever you give a number.

prepend()#

prepend() adds an item at the start, changing the collection:

const collection = collect([1, 2, 3, 4, 5])collection.prepend(0)collection.all()// [0, 1, 2, 3, 4, 5]

Laravel's takes a key as its second argument; a list has none.

pull()#

pull() removes the item at an index and returns it, changing the collection, and the later items move up:

const collection = collect(['prod-100', 'Desk'])collection.pull(1)// 'Desk'collection.all()// ['prod-100']

When there is no item at the index, it returns undefined, or the default you give.

push()#

push() adds items at the end, changing the collection:

const collection = collect([1, 2, 3, 4])collection.push(5)collection.all()// [1, 2, 3, 4, 5]

It takes several items: collection.push(6, 7).

put()#

put() sets the item at an index, changing the collection. An index past the end adds the item at the end, and a negative or fractional index throws a RangeError:

const collection = collect(['Desk', 'Chair'])collection.put(1, 'Sofa')collection.all()// ['Desk', 'Sofa']

random()#

random() returns a random item:

collect([1, 2, 3, 4, 5]).random()// 4 (retrieved randomly)

Given a number, it returns a collection of that many items, picked at random and kept in their order. A function receives the collection and returns the number. Asking for more items than the collection has throws a RangeError: "You requested 3 items, but there are only 2 items available.".

collect([1, 2, 3, 4, 5]).random(3).all()// [2, 4, 5] (retrieved randomly)

range()#

Static. Collection.range() returns the numbers from the first to the last, both included, counting by 1 or by the step you give:

Collection.range(3, 6).all()// [3, 4, 5, 6]Collection.range(10, 0, 5).all()// [10, 5, 0]

It takes numbers only, where PHP's range() also counts letters.

reduce()#

reduce() reduces the collection to one value, passing the result of each step to the next. The function receives the result so far, the item and its index, and the second argument is the first result:

collect([1, 2, 3]).reduce((carry, item) => carry + item, 0)// 6

Laravel's starting value is optional, and null when you leave it out; Oriel's is required.

reduceSpread()#

reduceSpread() reduces the collection to several values at once. The function receives them, then the item and its index, and returns them in an array; the arguments after the function are their starting values:

const [creditsLeft, prices] = collect([{ price: 3 }, { price: 6 }]).reduceSpread(  (credits: number, batch: number[], item) => [credits - item.price, [...batch, item.price]],  10,  [] as number[],)// creditsLeft: 1, prices: [3, 6]

A function that doesn't return an array throws a TypeError.

reject()#

reject() drops the items that pass the function, the opposite of filter():

const filtered = collect([1, 2, 3, 4]).reject((value) => value > 2)filtered.all()// [1, 2]

replace()#

replace() returns a copy with the items at some indexes replaced. Give it an object of indexes and values, or an array, which replaces from index 0. An index past the end adds the item at the end, and a negative or fractional index throws a RangeError:

const collection = collect(['Taylor', 'Abigail', 'James'])collection.replace({ 1: 'Victoria', 3: 'Finn' }).all()// ['Taylor', 'Victoria', 'James', 'Finn']collection.replace(['Victoria']).all()// ['Victoria', 'Abigail', 'James']

reverse()#

reverse() returns the items in the reverse order:

collect(['a', 'b', 'c', 'd', 'e']).reverse().all()// ['e', 'd', 'c', 'b', 'a']

Laravel's keeps each item's key; Oriel's numbers them from 0.

search() returns the index of the first item that is the value, compared loosely, or false when there is none:

const collection = collect([2, 4, 6, 8])collection.search(4)// 1

Pass true to compare strictly, or give a function:

collection.search('4', true)// falsecollection.search((item) => Number(item) > 5)// 2

select()#

select() keeps only the keys you give of each item, as a SQL SELECT does:

const users = collect([  { name: 'Taylor Otwell', role: 'Developer', status: 'active' },  { name: 'Victoria Faith', role: 'Researcher', status: 'active' },])users.select(['name', 'role']).all()// [{ name: 'Taylor Otwell', role: 'Developer' }, { name: 'Victoria Faith', role: 'Researcher' }]

shift()#

shift() removes the first item and returns it, changing the collection:

const collection = collect([1, 2, 3, 4, 5])collection.shift()// 1collection.all()// [2, 3, 4, 5]

Given a number, it removes that many from the start and returns them in a collection. A negative number throws a RangeError. As with pop(), shift(1) returns a collection.

shuffle()#

shuffle() returns the items in a random order:

collect([1, 2, 3, 4, 5]).shuffle().all()// [3, 2, 5, 1, 4] (generated randomly)

skip()#

skip() returns the items after the given number of them:

collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]).skip(4).all()// [5, 6, 7, 8, 9, 10]

skipUntil()#

skipUntil() skips items until one passes the function, or is the value, compared strictly, and returns the rest, that one included. When none does, the result is empty:

collect([1, 2, 3, 4]).skipUntil((item) => item >= 3).all()// [3, 4]collect([1, 2, 3, 4]).skipUntil(3).all()// [3, 4]

skipWhile()#

skipWhile() skips items while they pass the function, or are the value, and returns the rest:

collect([1, 2, 3, 4]).skipWhile((item) => item <= 3).all()// [4]

slice()#

slice() returns the items from an index on, or as many as you give:

const collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])collection.slice(4).all()// [5, 6, 7, 8, 9, 10]collection.slice(4, 2).all()// [5, 6]

It counts as PHP's array_slice() does, which Laravel's uses: a negative start counts from the end, and a negative length leaves that many items off the end:

const collection = collect([1, 2, 3, 4, 5])collection.slice(-2).all()// [4, 5]collection.slice(1, -1).all()// [2, 3, 4]

JavaScript's Array.slice() takes an end index instead of a length.

sliding()#

sliding() returns overlapping windows of the items, two at a time or as many as you give, each starting one item, or the step you give, after the last:

const collection = collect([1, 2, 3, 4, 5])collection.sliding(2).toArray()// [[1, 2], [2, 3], [3, 4], [4, 5]]collection.sliding(3, 2).toArray()// [[1, 2, 3], [3, 4, 5]]

sole()#

sole() returns the only item that passes the function, and throws when there isn't exactly one:

collect([1, 2, 3, 4]).sole((value) => value === 2)// 2

It also takes a key and a value, compared loosely, or a key, an operator and a value, and with nothing it returns the collection's only item:

const collection = collect([  { product: 'Desk', price: 200 },  { product: 'Chair', price: 100 },])collection.sole('product', 'Chair')// { product: 'Chair', price: 100 }

No match throws an ItemNotFoundError, "Item not found.", and more than one a MultipleItemsFoundError, "2 items were found.".

some()#

Another name for contains().

sort()#

sort() returns the items sorted, in ascending order: numbers by their value, dates by their time, and anything else as text, by localeCompare(). null and undefined come last:

collect([5, 3, 1, 2, 4]).sort().all()// [1, 2, 3, 4, 5]collect([10, 9, 1]).sort().all()// [1, 9, 10]

Give it a comparison function for another order, as you would to an array's sort():

collect([5, 3, 1, 2, 4])  .sort((a, b) => b - a)  .all()// [5, 4, 3, 2, 1]

Unlike an array's, it leaves the collection as it was. To sort objects, see sortBy().

sortBy()#

sortBy() sorts the items by a key's value, or by what a function returns:

const collection = collect([  { name: 'Desk', price: 200 },  { name: 'Chair', price: 100 },  { name: 'Bookcase', price: 150 },])collection.sortBy('price').pluck('name').all()// ['Chair', 'Bookcase', 'Desk']collection.sortBy((product) => product.name.length).pluck('name').all()// ['Desk', 'Chair', 'Bookcase']

The second argument is the direction, 'asc' or 'desc'. To sort by several keys, give a list of keys, each with its direction if you like, or of comparison functions:

const collection = collect([  { name: 'Taylor Otwell', age: 34 },  { name: 'Abigail Otwell', age: 30 },  { name: 'Taylor Otwell', age: 36 },  { name: 'Abigail Otwell', age: 32 },])collection.sortBy([['name', 'asc'], ['age', 'desc']]).all()// [//   { name: 'Abigail Otwell', age: 32 },//   { name: 'Abigail Otwell', age: 30 },//   { name: 'Taylor Otwell', age: 36 },//   { name: 'Taylor Otwell', age: 34 },// ]collection.sortBy([(a, b) => a.name.localeCompare(b.name), (a, b) => b.age - a.age]).all()

Items with the same value keep their order. A null or missing value comes last, in both directions, where Laravel puts it first in ascending order.

sortByDesc()#

sortByDesc() is sortBy() in descending order.

sortDesc()#

sortDesc() is sort() in descending order:

collect([5, 3, 1, 2, 4]).sortDesc().all()// [5, 4, 3, 2, 1]

splice()#

splice() removes the items from an index on and returns them, changing the collection:

const collection = collect([1, 2, 3, 4, 5])const chunk = collection.splice(2)chunk.all()// [3, 4, 5]collection.all()// [1, 2]

A second argument limits how many it removes, and a third is a list of items to put in their place. As in PHP, a negative index counts from the end, and a negative number leaves that many items at the end:

const collection = collect([1, 2, 3, 4, 5])const chunk = collection.splice(2, 1, [10, 11])chunk.all()// [3]collection.all()// [1, 2, 10, 11, 4, 5]

split()#

split() splits the collection into the given number of groups, as even as they can be, the first ones larger:

collect([1, 2, 3, 4, 5]).split(3).toArray()// [[1, 2], [3, 4], [5]]

splitIn()#

splitIn() splits the collection into the given number of groups, every group full except the last:

collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]).splitIn(3).toArray()// [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]

sum()#

sum() returns the sum of the items, or of a key's values, or of what a function returns:

collect([1, 2, 3, 4, 5]).sum()// 15collect([  { name: 'JavaScript: The Good Parts', pages: 176 },  { name: 'JavaScript: The Definitive Guide', pages: 1096 },]).sum('pages')// 1272collect([  { name: 'Chair', colors: ['Black'] },  { name: 'Desk', colors: ['Black', 'Mahogany'] },]).sum((product) => product.colors.length)// 3

Only numbers count: collect(['1', 2]).sum() is 2, where Laravel adds the numeric string.

take()#

take() returns the given number of items from the start, or from the end for a negative number:

collect([0, 1, 2, 3, 4, 5]).take(3).all()// [0, 1, 2]collect([0, 1, 2, 3, 4, 5]).take(-2).all()// [4, 5]

takeUntil()#

takeUntil() returns the items before the first one that passes the function, or is the value, compared strictly. When none does, it returns every item:

collect([1, 2, 3, 4]).takeUntil((item) => item >= 3).all()// [1, 2]collect([1, 2, 3, 4]).takeUntil(3).all()// [1, 2]

takeWhile()#

takeWhile() returns the items before the first one that fails the function, or isn't the value:

collect([1, 2, 3, 4]).takeWhile((item) => item < 3).all()// [1, 2]

tap()#

tap() passes the collection to the function and returns the collection, so you can look at it in the middle of a chain:

collect([2, 4, 3, 1, 5])  .sort()  .tap((collection) => console.log(collection.all()))  .shift()// 1

times()#

Static. Collection.times() calls the function the given number of times, with the numbers from 1, and returns a collection of the results:

Collection.times(10, (number) => number * 9).all()// [9, 18, 27, 36, 45, 54, 63, 72, 81, 90]

toArray()#

toArray() returns the items as an array, with each item that has a toArray() method, such as a model or a collection, turned into what it returns:

collect([collect([1, 2]), collect([3])]).toArray()// [[1, 2], [3]]

To get the items as they are, use all().

toJson()#

toJson() returns the items as JSON. toPrettyJson() indents it with four spaces, and toJSON() is what JSON.stringify() calls, so a collection inside an object is written as an array:

collect([{ name: 'Desk', price: 200 }]).toJson()// '[{"name":"Desk","price":200}]'JSON.stringify({ items: collect([1, 2]) })// '{"items":[1,2]}'

transform()#

transform() replaces each item with what the function returns, changing the collection:

const collection = collect([1, 2, 3, 4, 5])collection.transform((item) => item * 2)collection.all()// [2, 4, 6, 8, 10]

It returns the collection, typed with the new items. To keep the collection as it is, use map().

unique()#

unique() keeps the first of each value, compared strictly:

collect([1, 1, 2, 2, 3, 4, 2]).unique().all()// [1, 2, 3, 4]

Given a key or a function, it keeps the first item of each value it gives:

const collection = collect([  { name: 'iPhone 6', brand: 'Apple', type: 'phone' },  { name: 'iPhone 5', brand: 'Apple', type: 'phone' },  { name: 'Apple Watch', brand: 'Apple', type: 'watch' },  { name: 'Galaxy S6', brand: 'Samsung', type: 'phone' },  { name: 'Galaxy Gear', brand: 'Samsung', type: 'watch' },])collection.unique('brand').pluck('name').all()// ['iPhone 6', 'Galaxy S6']collection.unique((item) => item.brand + item.type).pluck('name').all()// ['iPhone 6', 'Apple Watch', 'Galaxy S6', 'Galaxy Gear']

Laravel's unique() compares loosely, so 1 and '1' are one value there and two here.

uniqueStrict()#

The same as unique(), which already compares strictly.

unless()#

unless() calls the function unless the first argument is truthy, the opposite of when():

const collection = collect([1, 2, 3])collection.unless(true, (collection) => collection.push(4))collection.unless(false, (collection) => collection.push(5))collection.all()// [1, 2, 3, 5]

unlessEmpty()#

Another name for whenNotEmpty().

unlessNotEmpty()#

Another name for whenEmpty().

unshift()#

unshift() adds items at the start, in the order you give them, changing the collection:

const collection = collect([3])collection.unshift(1, 2)collection.all()// [1, 2, 3]

unwrap()#

Static. Collection.unwrap() returns a collection's items as an array, and any other value as it is:

Collection.unwrap(collect(['John Doe']))// ['John Doe']Collection.unwrap('John Doe')// 'John Doe'

value()#

value() returns a key's value from the first item where it is truthy:

const collection = collect([  { product: 'Desk', price: 200 },  { product: 'Speaker', price: 400 },])collection.value('price')// 200

A price of 0 would be skipped. When no item has a truthy value, it returns undefined, or the default you give.

values()#

values() returns a copy of the collection. In Laravel it numbers the items from 0 again, which an Oriel collection always does.

when()#

when() calls the function when the first argument is truthy. The function receives the collection and the value:

const collection = collect([1, 2, 3])collection.when(true, (collection, value) => collection.push(4))collection.when(false, (collection, value) => collection.push(5))collection.all()// [1, 2, 3, 4]

A third argument is a function to call when the value is falsy. A function as the first argument is called with the collection, and its result decides. when() returns what the function returns, or the collection when it returns nothing.

whenEmpty()#

whenEmpty() calls the function when the collection is empty, and a second one, if you give it, when it isn't:

const collection = collect<string>([])collection.whenEmpty((collection) => collection.push('Adam'))collection.all()// ['Adam']

whenNotEmpty()#

whenNotEmpty() calls the function when the collection has items, and a second one, if you give it, when it is empty:

const collection = collect(['Michael', 'Tom'])collection.whenNotEmpty((collection) => collection.push('Adam'))collection.all()// ['Michael', 'Tom', 'Adam']

where()#

where() keeps the items whose key has the value, compared loosely:

const collection = collect([  { product: 'Desk', price: 200 },  { product: 'Chair', price: 100 },  { product: 'Bookcase', price: 150 },  { product: 'Door', price: 100 },])collection.where('price', 100).all()// [{ product: 'Chair', price: 100 }, { product: 'Door', price: 100 }]

An operator goes between the key and the value: =, ==, ===, !=, !==, <>, <, <=, > or >=:

collection.where('price', '>', 120).pluck('product').all()// ['Desk', 'Bookcase']

With a key alone, it keeps the items whose key is truthy. The key may be a function of the item.

whereBetween()#

whereBetween() keeps the items whose key is between two values, both included:

const collection = collect([  { product: 'Desk', price: 200 },  { product: 'Chair', price: 80 },  { product: 'Bookcase', price: 150 },  { product: 'Pencil', price: 30 },  { product: 'Door', price: 100 },])collection.whereBetween('price', [100, 200]).pluck('product').all()// ['Desk', 'Bookcase', 'Door']

whereIn()#

whereIn() keeps the items whose key is one of the values, compared strictly:

const collection = collect([  { product: 'Desk', price: 200 },  { product: 'Chair', price: 100 },  { product: 'Bookcase', price: 150 },  { product: 'Door', price: 100 },])collection.whereIn('price', [150, 200]).pluck('product').all()// ['Desk', 'Bookcase']

Laravel's whereIn() compares loosely, and whereInStrict() strictly.

whereInStrict()#

The same as whereIn(), which already compares strictly.

whereInstanceOf()#

whereInstanceOf() keeps the items that are instances of a class, or of one of a list of classes, and types the result with them:

const users = people.whereInstanceOf(User)

whereNotBetween()#

whereNotBetween() keeps the items whose key is outside two values:

const collection = collect([  { product: 'Desk', price: 200 },  { product: 'Chair', price: 80 },  { product: 'Bookcase', price: 150 },  { product: 'Pencil', price: 30 },  { product: 'Door', price: 100 },])collection.whereNotBetween('price', [100, 200]).pluck('product').all()// ['Chair', 'Pencil']

whereNotIn()#

whereNotIn() keeps the items whose key isn't one of the values, compared strictly:

const collection = collect([  { product: 'Desk', price: 200 },  { product: 'Chair', price: 100 },  { product: 'Bookcase', price: 150 },  { product: 'Door', price: 100 },])collection.whereNotIn('price', [150, 200]).pluck('product').all()// ['Chair', 'Door']

whereNotInStrict()#

The same as whereNotIn(), which already compares strictly.

whereNotNull()#

whereNotNull() keeps the items whose key isn't null or undefined, or, with no key, the items that aren't:

const collection = collect([{ name: 'Desk' }, { name: null }, { name: 'Bookcase' }])collection.whereNotNull('name').all()// [{ name: 'Desk' }, { name: 'Bookcase' }]

whereNull()#

whereNull() keeps the items whose key is null or undefined, an item without the key included, or, with no key, the items that are:

const collection = collect([{ name: 'Desk' }, { name: null }, { name: 'Bookcase' }])collection.whereNull('name').all()// [{ name: null }]

whereStrict()#

whereStrict() is where() with a key and a value, compared strictly:

collect([{ price: 100 }]).whereStrict('price', '100').count()// 0

wrap()#

Static. Collection.wrap() makes a collection of a value: an array's or a collection's items, nothing for null or undefined, and any other value as the one item:

Collection.wrap('John Doe').all()// ['John Doe']Collection.wrap(['John Doe']).all()// ['John Doe']Collection.wrap(null).all()// []

zip()#

zip() pairs each item with the item at the same index of the lists you give. A shorter list gives undefined:

const zipped = collect(['Chair', 'Desk']).zip([100, 200])zipped.toArray()// [['Chair', 100], ['Desk', 200]]

Higher order messages#

Laravel's higher order messages, such as $users->each->markAsVip() and $users->sum->votes, aren't in Oriel. Pass a function or a key: users.each((user) => user.markAsVip()), users.sum('votes').

Lazy collections#

Introduction#

A lazy collection reads its items one at a time, as you ask for them, so a large query or file never sits in memory all at once. Its items can come from an async source, such as a database cursor, so it is async: you go through it with for await, and its methods that return a value return a promise.

Your queries return one with lazy(), which reads the rows a chunk at a time, 1,000 by default:

for await (const user of User.lazy()) {  // ...}

Creating lazy collections#

LazyCollection.make() takes a function that returns an iterable, or an async one. A generator function is the usual choice:

app/Support/logLines.ts
import { createReadStream } from 'node:fs'import { createInterface } from 'node:readline'import { LazyCollection } from '@orieljs/framework'export function logLines(path: string): LazyCollection<string> {  return LazyCollection.make(() => createInterface({ input: createReadStream(path) }))}
const errors = await logLines('storage/logs/oriel.log')  .filter((line) => line.includes('"level":50'))  .take(10)  .collect()

collection.lazy() makes one from a collection.

Lazy collection methods#

A lazy collection has these methods. The first four return a new lazy collection, which reads nothing until you go through it; the others go through the items, and return a promise:

  • map(callback): each item passed through the callback, which may be async;
  • filter(callback): the items the callback passes;
  • take(count): the first items, and stops reading after them;
  • chunk(size): collections of size items;
  • each(callback): calls the callback with each item and its index; returning false stops;
  • first(callback?): the first item, or the first that passes the callback, or undefined;
  • count(): the number of items;
  • collect(): every item, in a Collection.
const count = await logLines('storage/logs/oriel.log')  .map((line) => JSON.parse(line) as { level: number })  .filter((entry) => entry.level >= 50)  .count()

Privacy policy ·

esc