Skip to content

Tolki Collection Methods List ​

These are the methods of the Collection class. Every example builds a collection with collect() and reads the items back with all() or toArray(). Each section ends with a box you can edit to try the method.

Methods List ​

add after all average avg before chunk chunkBy chunkWhile collapse collapseWithKeys collect combine concat contains containsManyItems containsOneItem containsStrict count countBy crossJoin diff diffAssoc diffAssocUsing diffKeys diffKeysUsing diffUsing doesntContain doesntContainStrict dot dump duplicates duplicatesStrict each eachSpread empty ensure escapeWhenCastingToString every except filter first firstOrFail firstWhere flatMap flatten flip forget forPage fromJson get getIterator getOrPut groupBy has hasAny hasMany hasSole implode intersect intersectAssoc intersectAssocUsing intersectByKeys intersectUsing isEmpty isNotEmpty join jsonSerialize keyBy keys last length make map mapInto mapSpread mapToDictionary mapToGroups mapWithKeys max median merge mergeRecursive min mode multiply nth offsetExists offsetGet offsetSet offsetUnset only pad partition percentage pipe pipeInto pipeThrough pluck pop prepend pull push put random range reduce reduceInto reduceSpread reduceWithKeys reject replace replaceRecursive reverse search select shift shuffle skip skipUntil skipWhile slice sliding sole some sort sortBy sortByDesc sortDesc sortKeys sortKeysDesc sortKeysUsing splice split splitIn sum Symbol.iterator Symbol.toPrimitive take takeUntil takeWhile tap times toArray toBase toJson toJSON toPrettyJson toString transform undot union 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

Methods Details ​

add ​

Add an item to the end of the collection, under the next free integer key.

The same operation on plain arrays and objects is in the utilities list.

WARNING

Unlike most other collection methods, add does not return a new modified collection; it modifies and returns the collection it is called on.

js
import { collect } from "@tolki/collection";

const items = collect([1, 2]);

items.add(3).all();
// => [1, 2, 3]

items.all();
// => [1, 2, 3]

collect({ 5: "a" }).add("z").all();
// => { 5: "a", 6: "z" }

▶ Try it · collect(items).add(item)

Result[1,2,3]

after ​

Get the item after the given item, or null when the item is not found or is the last one.

Laravel: after()

The search is loose by default, so "4" finds 4 (see Loose and strict comparison). Pass true as the second argument to compare strictly, or pass a callback to find the first item that passes a test.

The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

collect([1, 2, 3, 4, 5]).after(3);
// => 4

collect([1, 2, 3, 4, 5]).after(5);
// => null

collect([2, 4, 6, 8]).after("4");
// => 6

collect([2, 4, 6, 8]).after("4", true);
// => null

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

▶ Try it · collect(items).after(value, strict)

Result4

all ​

Get the items of the collection: an array for a list, a plain object for a keyed collection.

Laravel: all()

all() hands back the collection's own items, not a copy. See Values in the differences.

js
import { collect } from "@tolki/collection";

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

collect({ a: 1, b: 2 }).all();
// => { a: 1, b: 2 }

▶ Try it · collect(items).all()

Result{"a":1,"b":2}

average ​

Alias for the avg method.

Laravel: average()

js
import { collect } from "@tolki/collection";

collect([1, 1, 2, 4]).average();
// => 2

▶ Try it · collect(items).average(key)

Result20

avg ​

Get the average value of a given key, or of the items themselves when no key is given. Items that are null are left out, and an empty collection gives null.

Laravel: avg()

The callback also receives the key as its second argument (see JavaScript-only additions). Numeric strings are added as numbers, and a value that cannot be added, such as a non-numeric string or an array, throws a TypeError.

js
import { collect } from "@tolki/collection";

collect([{ foo: 10 }, { foo: 10 }, { foo: 20 }, { foo: 40 }]).avg("foo");
// => 20

collect([1, 1, 2, 4]).avg();
// => 2

collect([10, 20, 30]).avg((value, key) => value + key);
// => 21

collect(["1", "2", 3]).avg();
// => 2

collect([]).avg();
// => null

collect(["a", 1]).avg();
// => throws TypeError

▶ Try it · collect(items).avg(key)

Result20

before ​

Get the item before the given item, or null when the item is not found or is the first one. It is the opposite of after and takes the same arguments.

Laravel: before()

The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

collect([1, 2, 3, 4, 5]).before(3);
// => 2

collect([1, 2, 3, 4, 5]).before(1);
// => null

collect([2, 4, 6, 8]).before("4", true);
// => null

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

▶ Try it · collect(items).before(value, strict)

Result2

chunk ​

Break the collection into multiple, smaller collections of a given size.

Laravel: chunk()

Each chunk keeps its items' keys, so a later chunk of a list starts at its original position. Pass false as the second argument to renumber each chunk from 0. A size of 0 or below gives an empty collection.

The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

collect([1, 2, 3, 4, 5]).chunk(2).toArray();
// => [{ 0: 1, 1: 2 }, { 2: 3, 3: 4 }, { 4: 5 }]

collect([1, 2, 3, 4, 5]).chunk(2, false).toArray();
// => [[1, 2], [3, 4], [5]]

collect({ a: 1, b: 2, c: 3 }).chunk(2).toArray();
// => [{ a: 1, b: 2 }, { c: 3 }]

▶ Try it · collect(items).chunk(size)

Result[{"0":1,"1":2},{"2":3,"3":4},{"4":5}]

chunkBy ​

Break the collection into chunks of adjacent items that share the same value for a key or callback.

Laravel: chunkBy()

Unlike groupBy, items with the same value that are not next to each other land in separate chunks. A key may be a dot-notation path, and values are compared loosely, so 1 and "1" share a chunk (see Loose and strict comparison).

INFO

A list's chunks are lists, so each one counts from 0 again. In Laravel a later chunk keeps the keys its items had (see Keys and order).

The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

collect([1, 1, 2, 2, 1])
  .chunkBy((value) => value)
  .toArray();
// => [[1, 1], [2, 2], [1]]

collect([{ parent: "a" }, { parent: "a" }, { parent: "b" }])
  .chunkBy("parent")
  .toArray();
// => [[{ parent: "a" }, { parent: "a" }], [{ parent: "b" }]]

collect([1, "1", 2])
  .chunkBy((value) => value)
  .toArray();
// => [[1, "1"], [2]]

▶ Try it · collect(items).chunkBy(callback)

Result[[1,1],[2,2],[1]]

chunkWhile ​

Break the collection into chunks with a callback that decides whether the next item joins the current chunk.

Laravel: chunkWhile()

The callback receives the value, its key and the chunk built so far as a collection, so chunk.last() works. Return true to keep adding to the chunk.

INFO

A list's chunks are lists, so each one counts from 0 again. In Laravel a later chunk keeps the keys its items had (see Keys and order).

The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

collect("AABBCCCD".split(""))
  .chunkWhile((value, key, chunk) => value === chunk.last())
  .toArray();
// => [["A", "A"], ["B", "B"], ["C", "C", "C"], ["D"]]

collect([1, 2, 4, 5, 7])
  .chunkWhile((value, key, chunk) => value === chunk.last() + 1)
  .toArray();
// => [[1, 2], [4, 5], [7]]

▶ Try it · collect(items).chunkWhile(callback)

Result[["A","A"],["B","B"],["C","C","C"],["D"]]

collapse ​

Collapse a collection of arrays, objects or collections into a single, flat collection.

Laravel: collapse()

Arrays join into a list, and objects merge into a keyed collection. To keep each item's keys, use collapseWithKeys. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

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

collect([{ a: 1 }, { b: 2 }])
  .collapse()
  .all();
// => { a: 1, b: 2 }

collect([collect([1, 2]), collect([3])])
  .collapse()
  .all();
// => [1, 2, 3]

▶ Try it · collect(items).collapse()

Result[1,2,3,4,5,6,7,8,9]

collapseWithKeys ​

Collapse a collection of arrays, objects or collections into one collection, keeping the keys. A later item's key replaces an earlier one's.

Laravel: collapseWithKeys()

A flat collection collapses to an empty one.

js
import { collect } from "@tolki/collection";

collect([
  { first: collect([1, 2, 3]) },
  { second: [4, 5, 6] },
  { third: collect([7, 8, 9]) },
])
  .collapseWithKeys()
  .toArray();
// => { first: [1, 2, 3], second: [4, 5, 6], third: [7, 8, 9] }

collect([{ a: 1 }, { b: 2 }, { a: 3 }])
  .collapseWithKeys()
  .all();
// => { a: 3, b: 2 }

collect([1, 2, 3]).collapseWithKeys().all();
// => []

▶ Try it · collect(items).collapseWithKeys()

Result{"a":3,"b":2}

collect ​

Get a new collection holding a copy of the items.

Laravel: collect()

This is the collect method of a collection. The collect() function that builds a collection from an array is a separate helper.

js
import { collect } from "@tolki/collection";

const original = collect([1, 2, 3]);
const copy = original.collect();

copy.add(4).all();
// => [1, 2, 3, 4]

original.all();
// => [1, 2, 3]

▶ Try it · collect(items).collect()

Result[1,2,3]

combine ​

Combine the values of the collection, as keys, with the values of another array or collection.

Laravel: combine()

The collection's own keys are not used. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

collect(["name", "age"]).combine(["George", 29]).all();
// => { name: "George", age: 29 }

▶ Try it · collect(items).combine(values)

Result{"name":"George","age":29}

concat ​

Append the values of an array, object or collection onto the end of the collection.

Laravel: concat()

The appended values get new integer keys, even when they came from a keyed source. To keep keys, use merge().

js
import { collect } from "@tolki/collection";

collect(["John Doe"]).concat(["Jane Doe"]).concat({ name: "Johnny Doe" }).all();
// => ["John Doe", "Jane Doe", "Johnny Doe"]

collect({ a: 1, b: 2 }).concat({ c: 3, d: 4 }).all();
// => { 0: 3, 1: 4, a: 1, b: 2 }

▶ Try it · collect(items).concat(other)

Result["John Doe","Jane Doe"]

contains ​

Determine whether the collection contains a given item.

Laravel: contains()

Pass a callback to test each item, a value to look for, or a key and a value to look for a matching pair in the items. Comparisons are loose, so "2" matches 2 (see Loose and strict comparison). Use containsStrict to compare strictly, and doesntContain for the opposite. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

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

collect({ name: "Desk", price: 100 }).contains("Desk");
// => true

collect({ name: "Desk", price: 100 }).contains("New York");
// => false

collect([
  { product: "Desk", price: 200 },
  { product: "Chair", price: 100 },
]).contains("product", "Bookcase");
// => false

collect([1, 2, 3]).contains("2");
// => true

▶ Try it · collect(items).contains(value)

Resulttrue

containsManyItems ​

Determine whether the collection holds more than one item, or, with a callback, whether more than one item passes the test.

Deprecated: use hasMany() instead.

js
import { collect } from "@tolki/collection";

collect([1, 2]).containsManyItems();
// => true

collect([1]).containsManyItems();
// => false

collect([1, 2, 2]).containsManyItems((value) => value === 2);
// => true

▶ Try it · collect(items).containsManyItems()

Resulttrue

containsOneItem ​

Determine whether the collection holds exactly one item, or, with a callback, whether exactly one item passes the test.

Deprecated: use hasSole() instead.

js
import { collect } from "@tolki/collection";

collect([1]).containsOneItem();
// => true

collect([]).containsOneItem();
// => false

collect([1, 2, 3]).containsOneItem((value) => value >= 2);
// => false

collect([1, 2, 3]).containsOneItem((value) => value < 2);
// => true

▶ Try it · collect(items).containsOneItem()

Resulttrue

containsStrict ​

Determine whether the collection contains a given item, comparing strictly.

Laravel: containsStrict()

It takes the same arguments as contains, but "2" does not match 2. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

collect([1, 2, 3]).containsStrict(2);
// => true

collect([1, 2, 3]).containsStrict("2");
// => false

collect([{ id: 1 }]).containsStrict("id", 1);
// => true

collect([{ id: 1 }]).containsStrict("id", "1");
// => false

▶ Try it · collect(items).containsStrict(value)

Resultfalse

count ​

Get the total number of items in the collection.

Laravel: count()

The length property gives the same number. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

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

collect({ a: 1, b: 2 }).count();
// => 2

collect([]).count();
// => 0

▶ Try it · collect(items).count()

Result4

countBy ​

Count the occurrences of values in the collection, by the value itself, a key or a callback.

Laravel: countBy()

The result is a keyed collection of counts. An @tolki/enum case counts as its value (see JavaScript-only additions).

js
import { collect } from "@tolki/collection";

collect([1, 2, 2, 2, 3]).countBy().all();
// => { 1: 1, 2: 3, 3: 1 }

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

collect([{ type: "a" }, { type: "b" }, { type: "a" }])
  .countBy("type")
  .all();
// => { a: 2, b: 1 }

▶ Try it · collect(items).countBy(callback)

Result{"1":1,"2":3,"3":1}

crossJoin ​

Cross join the collection's values among the given arrays or collections, returning every possible combination.

Laravel: crossJoin()

Keys are ignored: each list contributes its values. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

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"],
// ]

▶ Try it · collect(items).crossJoin(other)

Result[[1,"a"],[1,"b"],[2,"a"],[2,"b"]]

diff ​

Get the values in the collection that are not present in the given array or collection.

Laravel: diff()

A keyed collection keeps its keys. Values are compared as strings, so 2 matches "2". Array and object items are matched by identity: see Differences from Laravel. The same operation on plain arrays and objects is in the utilities list.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

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

collect({ a: 1, b: 2, c: 3 }).diff([2]).all();
// => { a: 1, c: 3 }

collect([1, 2, 3]).diff(["2"]).all();
// => [1, 3]

▶ Try it · collect(items).diff(other)

Result[1,3,5]

diffAssoc ​

Get the key and value pairs in the collection that are not present in the given array or collection.

Laravel: diffAssoc()

A pair is left out only when both its key and its value match. The same operation on plain arrays and objects is in the utilities list.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

collect({ color: "orange", type: "fruit", remain: 6 })
  .diffAssoc({ color: "yellow", type: "fruit", remain: 3, used: 6 })
  .all();
// => { color: "orange", remain: 6 }

▶ Try it · collect(items).diffAssoc(other)

Result{"color":"orange","remain":6}

diffAssocUsing ​

Get the key and value pairs that are not present in the given items, comparing keys with a callback of your own.

Laravel: diffAssocUsing()

The callback receives two keys and answers 0, or true, when they match. Values are still compared strictly. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

const ignoreCase = (a, b) =>
  String(a).toLowerCase() === String(b).toLowerCase() ? 0 : 1;

collect({ color: "orange", type: "fruit", remain: 6 })
  .diffAssocUsing({ Color: "yellow", Type: "fruit", Remain: 3 }, ignoreCase)
  .all();
// => { color: "orange", remain: 6 }

▶ Try it · collect(items).diffAssocUsing(other, callback)

Result{"color":"orange","remain":6}

diffKeys ​

Get the key and value pairs in the collection whose keys are not present in the given array or collection.

Laravel: diffKeys()

Values are ignored. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

collect({ one: 10, two: 20, three: 30, four: 40, five: 50 })
  .diffKeys({ two: 2, four: 4, six: 6, eight: 8 })
  .all();
// => { one: 10, three: 30, five: 50 }

collect([1, 3, 5, 7, 8]).diffKeys([1, 3, 5]).all();
// => [7, 8]

▶ Try it · collect(items).diffKeys(other)

Result{"one":10,"three":30}

diffKeysUsing ​

Get the key and value pairs whose keys are not present in the given items, comparing keys with a callback of your own.

The callback receives two keys and answers 0, or true, when they match. Values are ignored. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

const ignoreCase = (a, b) =>
  String(a).toLowerCase() === String(b).toLowerCase() ? 0 : 1;

collect({ id: 1, first_word: "Hello" })
  .diffKeysUsing({ ID: 123, foo_bar: "Hello" }, ignoreCase)
  .all();
// => { first_word: "Hello" }

▶ Try it · collect(items).diffKeysUsing(other, callback)

Result{"first_word":"Hello"}

diffUsing ​

Get the values in the collection that are not present in the given items, comparing values with a callback of your own.

The callback receives two values and answers 0, or true, when they match. Keys are kept. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

const ignoreCase = (a, b) =>
  String(a).toLowerCase() === String(b).toLowerCase() ? 0 : 1;

collect(["Green", "Brown", "Blue"])
  .diffUsing(["GREEN", "Yellow"], ignoreCase)
  .all();
// => ["Brown", "Blue"]

collect(["Green", "Brown", "Blue"])
  .diffUsing(["GREEN", "Yellow"], (a, b) => a.toLowerCase() === b.toLowerCase())
  .all();
// => ["Brown", "Blue"]

▶ Try it · collect(items).diffUsing(other, callback)

Result["Brown","Blue"]

doesntContain ​

Determine whether the collection does not contain a given item.

Laravel: doesntContain()

It takes the same arguments as contains and gives the opposite answer. Comparisons are loose, so "2" matches 2.

js
import { collect } from "@tolki/collection";

collect([1, 2, 3, 4, 5]).doesntContain((value, key) => value < 5);
// => false

collect({ name: "Desk", price: 100 }).doesntContain("Table");
// => true

collect({ name: "Desk", price: 100 }).doesntContain("Desk");
// => false

collect([{ product: "Desk" }, { product: "Chair" }]).doesntContain(
  "product",
  "Bookcase",
);
// => true

▶ Try it · collect(items).doesntContain(value)

Resulttrue

doesntContainStrict ​

Determine whether the collection does not contain a given item, comparing strictly.

Laravel: doesntContainStrict()

It takes the same arguments as doesntContain, but "2" does not match 2.

js
import { collect } from "@tolki/collection";

collect([1, 2, 3]).doesntContainStrict(4);
// => true

collect([1, 2, 3]).doesntContainStrict(2);
// => false

collect([1, 2, 3]).doesntContainStrict("2");
// => true

▶ Try it · collect(items).doesntContainStrict(value)

Resulttrue

dot ​

Flatten a multi-dimensional collection into a single level that uses "dot" notation to show depth.

Laravel: dot()

Pass a depth to stop flattening early. The keys follow the rules in Dot Notation. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

collect({ products: { desk: { price: 100 } } })
  .dot()
  .all();
// => { "products.desk.price": 100 }

collect([{ a: 1 }, { b: { c: 2 } }])
  .dot()
  .all();
// => { "0.a": 1, "1.b.c": 2 }

collect({ a: { b: { c: 1 } } })
  .dot(1)
  .all();
// => { "a.b": { c: 1 } }

▶ Try it · collect(items).dot()

Result{"products.desk.price":100}

dump ​

Dump the collection's items to the console, along with any further values you pass, and return the collection.

Laravel: dump()

dump() logs the items with console.log, so the example below logs the two names to the console. Because it returns the collection, you can drop it into the middle of a chain. There is no dd(): see Not portable.

js
import { collect } from "@tolki/collection";

collect(["John Doe", "Jane Doe"]).dump().all();
// => ["John Doe", "Jane Doe"]

collect([1, 2, 3])
  .dump("after the dump")
  .map((value) => value * 2)
  .all();
// => [2, 4, 6]

duplicates ​

Get the values that appear more than once, each under the key of its second and later appearances.

Laravel: duplicates()

The keys are the positions of the repeated values, as in chunk, because the keys are the answer. See Keys and order. Pass a key, or a callback, to check the values it reads from each item; the result holds those values. Values are compared loosely, so 1 and "1" are duplicates (see Loose and strict comparison). Use duplicatesStrict to compare strictly.

js
import { collect } from "@tolki/collection";

collect(["a", "b", "a", "c", "b"]).duplicates().all();
// => { 2: "a", 4: "b" }

collect([
  { email: "abigail@example.com", position: "Developer" },
  { email: "james@example.com", position: "Designer" },
  { email: "victoria@example.com", position: "Developer" },
])
  .duplicates("position")
  .all();
// => { 2: "Developer" }

collect([1, "1", 2]).duplicates().all();
// => { 1: "1" }

▶ Try it · collect(items).duplicates(key)

Result{"2":"a","4":"b"}

duplicatesStrict ​

Get the values that appear more than once, comparing strictly.

Laravel: duplicatesStrict()

It takes the same arguments as duplicates, but "1" does not match 1.

js
import { collect } from "@tolki/collection";

collect([1, "1", 2, "2", 2]).duplicatesStrict().all();
// => { 4: 2 }

collect([1, "1"]).duplicatesStrict().all();
// => {}

▶ Try it · collect(items).duplicatesStrict(key)

Result{"4":2}

each ​

Run a callback over each item, and return the collection.

Laravel: each()

The callback receives the item and its key. Return false from it to stop iterating.

js
import { collect } from "@tolki/collection";

const seen = [];

collect([1, 2, 3, 4]).each((item, key) => {
  seen.push(item);

  if (item === 2) {
    return false;
  }
});

seen;
// => [1, 2]

collect({ a: 1, b: 2 })
  .each((item, key) => {})
  .all();
// => { a: 1, b: 2 }

▶ Try it · collect(items).each(callback)

Result[[0,1],[1,2]]

eachSpread ​

Run a callback over each nested row, passing the row's values as separate arguments, and return the collection.

Laravel: eachSpread()

The row's key arrives after its values. Return false from the callback to stop iterating. A plain object or a Map row is spread by its values, and a scalar row is passed whole: see JavaScript-only additions.

js
import { collect } from "@tolki/collection";

const seen = [];

collect([
  ["John Doe", 35],
  ["Jane Doe", 33],
]).eachSpread((name, age, key) => {
  seen.push(`${key}: ${name} is ${age}`);
});

seen;
// => ["0: John Doe is 35", "1: Jane Doe is 33"]

const first = [];

collect([
  ["John Doe", 35],
  ["Jane Doe", 33],
]).eachSpread((name, age) => {
  first.push(name);

  return false;
});

first;
// => ["John Doe"]

▶ Try it · collect(items).eachSpread(callback)

Result["0: John Doe is 35","1: Jane Doe is 33"]

empty ​

The static empty method creates a collection with no items.

js
import { Collection } from "@tolki/collection";

Collection.empty().all();
// => []

Collection.empty().isEmpty();
// => true

In TypeScript, name the item type yourself with Collection.empty<string>().

▶ Try it · Collection.empty()

Result[]

ensure ​

Check that every item has the expected type, and throw when one does not.

Laravel: ensure()

The type is a class, a type name such as "int", "float", "string", "bool", "array" or "null", or a list of them. When an item matches none, ensure() throws an UnexpectedValueException that names the item's type and position. It also takes JavaScript's typeof names: see JavaScript-only additions. A class passed as itself accepts its subclasses too, while a class named as a string matches only that class.

ensure() checks the items now. It does not stop you adding items of another type later.

js
import { collect } from "@tolki/collection";

collect([1, 2, 3]).ensure("int").all();
// => [1, 2, 3]

collect([1, "2", 3]).ensure("int");
// => throws UnexpectedValueException

collect([1, "2", true]).ensure(["int", "string", "bool"]).all();
// => [1, "2", true]

collect([new Date(0), new Date(1)])
  .ensure(Date)
  .count();
// => 2

collect([1, 1.5]).ensure("number").all();
// => [1, 1.5]

▶ Try it · collect(items).ensure(type)

Result[1,2,3]

escapeWhenCastingToString ​

Make the collection HTML-escape its string form, or stop it doing so.

Casting a collection to a string gives its JSON. Once escaping is on, that string has &, <, >, " and ' replaced with HTML entities. The escaping applies to the string cast alone: toJson() is unchanged. Pass false to turn escaping off again.

WARNING

Unlike most other collection methods, escapeWhenCastingToString does not return a new modified collection; it modifies and returns the collection it is called on.

js
import { collect } from "@tolki/collection";

const items = collect(["<b>"]);

String(items);
// => '["<b>"]'

items.escapeWhenCastingToString();

String(items);
// => '[&quot;&lt;b&gt;&quot;]'

items.toJson();
// => '["<b>"]'

items.escapeWhenCastingToString(false);

String(items);
// => '["<b>"]'

▶ Try it · collect(items).escapeWhenCastingToString(escape)

Result"[&quot;&lt;b&gt;&quot;]"

every ​

Determine whether all items pass a truth test.

Laravel: every()

Besides a callback, every() takes a key and a value, or a key, an operator and a value. An empty collection passes.

The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

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

collect([]).every((value, key) => value > 2);
// => true

collect([{ id: 1 }, { id: 1 }]).every("id", 1);
// => true

collect([{ id: 1 }, { id: 2 }]).every("id", ">=", 1);
// => true

▶ Try it · collect(items).every(callback)

Resultfalse

except ​

Get all items except those with the given keys.

Laravel: except()

Pass the keys as an array or a collection, or as separate arguments. For the inverse, see only. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

collect({ product_id: 1, price: 100, discount: false })
  .except(["price", "discount"])
  .all();
// => { product_id: 1 }

collect({ a: 1, b: 2, c: 3 }).except("a", "c").all();
// => { b: 2 }

collect([1, 2, 3, 4]).except([0, 2]).all();
// => [2, 4]

▶ Try it · collect(items).except(keys)

Result{"product_id":1}

filter ​

Keep only the items that pass a truth test.

Laravel: filter()

The callback receives the item and its key. Without a callback, filter() drops every item that is falsy by PHP's rules. For the inverse, see reject. The same operation on plain arrays and objects is in the utilities list.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

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

collect([1, 2, 3, null, false, "", 0, []]).filter().all();
// => [1, 2, 3]

collect({ id: 1, first: "Hello", second: "World" })
  .filter((value, key) => key !== "id")
  .all();
// => { first: "Hello", second: "World" }

▶ Try it · collect(items).filter(callback)

Result[3,4]

first ​

Get the first item, or the first item that passes a truth test.

Laravel: first()

With no match, first() returns null. Pass a default, or a callback that returns one, as the second argument. To throw instead, use firstOrFail. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

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

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

collect([]).first();
// => null

collect([]).first(null, "none");
// => "none"

▶ Try it · collect(items).first(callback, fallback)

Result3

firstOrFail ​

Get the first item, or the first item that passes a test, and throw when there is none.

Laravel: firstOrFail()

It works like first, but throws an ItemNotFoundException when no item matches, or when the collection is empty. Besides a callback, it takes a key and a value, or a key, an operator and a value.

js
import { collect } from "@tolki/collection";

collect([1, 2, 3, 4]).firstOrFail((value, key) => value > 2);
// => 3

collect([{ id: 1 }, { id: 2 }]).firstOrFail("id", "==", 2);
// => { id: 2 }

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

collect([]).firstOrFail();
// => throws ItemNotFoundException

▶ Try it · collect(items).firstOrFail(callback)

Result3

firstWhere ​

Get the first item with the given key and value.

Laravel: firstWhere()

It takes the arguments of where: a key and a value, or a key, an operator and a value. With a key alone, it returns the first item where that key is truthy. When nothing matches, it returns null.

js
import { collect } from "@tolki/collection";

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 }

users.firstWhere("age", ">=", 18);
// => { name: "Diego", age: 23 }

users.firstWhere("age");
// => { name: "Linda", age: 14 }

users.firstWhere("age", ">", 100);
// => null

▶ Try it · collect(items).firstWhere(key, operator, value)

Result{"name":"Diego","age":23}

flatMap ​

Map each item with a callback, then flatten the result by one level.

Laravel: flatMap()

The callback receives the item and its key, and returns an array, an object or a collection. The returned items are merged into one collection.

js
import { collect } from "@tolki/collection";

collect([1, 2, 3])
  .flatMap((value) => [value, value * 10])
  .all();
// => [1, 10, 2, 20, 3, 30]

collect([{ name: "Sally" }, { school: "Arkansas" }, { age: 28 }])
  .flatMap((values) =>
    Object.fromEntries(
      Object.entries(values).map(([key, value]) => [
        key,
        String(value).toUpperCase(),
      ]),
    ),
  )
  .all();
// => { name: "SALLY", school: "ARKANSAS", age: "28" }

▶ Try it · collect(items).flatMap(callback)

Result[1,10,2,20,3,30]

flatten ​

Flatten a multi-dimensional collection into a single level.

Laravel: flatten()

Pass a depth to flatten only that many levels. A nested collection is flattened too, and any other object that is not a plain object is kept whole. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

collect({ name: "Taylor", languages: ["PHP", "JavaScript"] })
  .flatten()
  .all();
// => ["Taylor", "PHP", "JavaScript"]

collect([1, [2, [3, 4]], 5])
  .flatten(1)
  .all();
// => [1, 2, [3, 4], 5]

collect({
  Apple: [{ name: "iPhone 6S", brand: "Apple" }],
  Samsung: [{ name: "Galaxy S7", brand: "Samsung" }],
})
  .flatten(1)
  .all();
// => [{ name: "iPhone 6S", brand: "Apple" }, { name: "Galaxy S7", brand: "Samsung" }]

▶ Try it · collect(items).flatten(depth)

Result[1,2,[3,4],5]

flip ​

Swap the collection's keys with their values.

Laravel: flip()

The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

collect({ name: "Taylor", framework: "Laravel" }).flip().all();
// => { Taylor: "name", Laravel: "framework" }

collect(["a", "b", "c"]).flip().all();
// => { a: 0, b: 1, c: 2 }

▶ Try it · collect(items).flip()

Result{"Taylor":"name","Laravel":"framework"}

forget ​

Remove one or more items by key.

Laravel: forget()

Pass one key, an array of keys or a collection of keys. Each key is removed as it is, so a dotted key such as "a.b" does not reach a nested value; the utilities list has the version that reads a path.

INFO

A list stays a list, so the items after the removed ones move down. In Laravel they keep the keys they had. See Keys and order.

WARNING

Unlike most other collection methods, forget does not return a new modified collection; it modifies and returns the collection it is called on.

js
import { collect } from "@tolki/collection";

const items = collect({ name: "Taylor", framework: "Laravel" });

items.forget("name").all();
// => { framework: "Laravel" }

items.all();
// => { framework: "Laravel" }

items.forget(["name", "framework"]).all();
// => {}

collect([1, 2, 3, 4]).forget([0, 2]).all();
// => [2, 4]

collect({ a: { b: 1 } })
  .forget("a.b")
  .all();
// => { a: { b: 1 } }

▶ Try it · collect(items).forget(keys)

Result{"framework":"Laravel"}

forPage ​

Get the items that belong on a page, given the page number and the number of items per page.

Laravel: forPage()

Pages count from 1.

js
import { collect } from "@tolki/collection";

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

collect([1, 2, 3, 4, 5]).forPage(2, 3).all();
// => [4, 5]

collect({ a: 1, b: 2, c: 3 }).forPage(2, 1).all();
// => { b: 2 }

▶ Try it · collect(items).forPage(page, perPage)

Result[4,5,6]

fromJson ​

The static fromJson method creates a collection by decoding a JSON string.

Laravel: fromJson()

An object becomes a keyed collection and an array a list. JSON that cannot be decoded gives an empty collection. The depth and flags arguments are accepted and ignored: see Not portable.

js
import { Collection } from "@tolki/collection";

Collection.fromJson('{"name":"Taylor Otwell","role":"Developer"}').all();
// => { name: "Taylor Otwell", role: "Developer" }

Collection.fromJson("[1,2,3]").all();
// => [1, 2, 3]

Collection.fromJson("{bad").all();
// => []

▶ Try it · Collection.fromJson(json)

Result[1,2,3]

get ​

Get the item at a key, or a default when the key is absent.

Laravel: get()

The default may be a value or a callback that returns one. The key is looked up as it is, not as a path, so get("a.b") does not read a nested value; the utilities list has the version that reads a path.

js
import { collect } from "@tolki/collection";

const user = collect({ name: "Taylor", framework: "Laravel" });

user.get("name");
// => "Taylor"

user.get("age", 34);
// => 34

user.get("email", () => "taylor@example.com");
// => "taylor@example.com"

collect({ a: { b: 1 } }).get("a.b", "default");
// => "default"

▶ Try it · collect(items).get(key, fallback)

Result34

getIterator ​

Get an iterator over the collection's values.

for...of and spreading use this iterator. Call next() to step through the values by hand.

js
import { collect } from "@tolki/collection";

const iterator = collect([10, 20]).getIterator();

iterator.next();
// => { value: 10, done: false }

iterator.next();
// => { value: 20, done: false }

iterator.next().done;
// => true

[...collect({ a: 1, b: 2 }).getIterator()];
// => [1, 2]

▶ Try it · collect(items).getIterator()

Result[1,2]

getOrPut ​

Get the item at a key. When the key is absent, put a value under it and return that value.

The value may be a callback, which runs only when the key is absent.

WARNING

Unlike most other collection methods, getOrPut does not return a new modified collection; it modifies the collection it is called on.

js
import { collect } from "@tolki/collection";

const items = collect({ a: 1, b: 2 });

items.getOrPut("b", 3);
// => 2

items.getOrPut("c", 3);
// => 3

items.all();
// => { a: 1, b: 2, c: 3 }

let calls = 0;

items.getOrPut("d", () => {
  calls += 1;

  return 4;
});
// => 4

items.getOrPut("d", () => {
  calls += 1;

  return 5;
});
// => 4

calls;
// => 1

▶ Try it · collect(items).getOrPut(key, value)

Result{"returned":3,"collection":{"a":1,"b":2,"c":3}}

groupBy ​

Group the items by a key or a callback.

Laravel: groupBy()

Each group is a collection, so use toArray() to read them all at once. Pass a callback to compute the group key. Pass an array of keys and callbacks to group in levels, one per entry.

Pass true as the second argument to keep each item's key inside its group. A list's items then keep their positions, as chunk does. See Keys and order.

js
import { collect } from "@tolki/collection";

const orders = collect([
  { account_id: "account-x10", product: "Chair" },
  { account_id: "account-x10", product: "Bookcase" },
  { account_id: "account-x11", product: "Desk" },
]);

orders.groupBy("account_id").toArray();
// => {
//   "account-x10": [
//     { account_id: "account-x10", product: "Chair" },
//     { account_id: "account-x10", product: "Bookcase" },
//   ],
//   "account-x11": [{ account_id: "account-x11", product: "Desk" }],
// }

orders.groupBy((item, key) => item.account_id.slice(-3)).toArray();
// => {
//   x10: [
//     { account_id: "account-x10", product: "Chair" },
//     { account_id: "account-x10", product: "Bookcase" },
//   ],
//   x11: [{ account_id: "account-x11", product: "Desk" }],
// }

collect(["a", "b", "c", "d"])
  .groupBy((value, key) => (key % 2 === 0 ? "even" : "odd"), true)
  .toArray();
// => { even: { 0: "a", 2: "c" }, odd: { 1: "b", 3: "d" } }

collect({
  10: { user: 1, skill: 1, roles: ["Role_1", "Role_3"] },
  20: { user: 2, skill: 2, roles: ["Role_2"] },
})
  .groupBy(["skill", (item) => item.roles], true)
  .toArray();
// => {
//   1: {
//     Role_1: { 10: { user: 1, skill: 1, roles: ["Role_1", "Role_3"] } },
//     Role_3: { 10: { user: 1, skill: 1, roles: ["Role_1", "Role_3"] } },
//   },
//   2: { Role_2: { 20: { user: 2, skill: 2, roles: ["Role_2"] } } },
// }

▶ Try it · collect(items).groupBy(key, preserveKeys)

Result{"account-x10":[{"account_id":"account-x10","product":"Chair"},{"account_id":"account-x10","product":"Bookcase"}],"account-x11":[{"account_id":"account-x11","product":"Desk"}]}

has ​

Determine whether a key exists in the collection.

Laravel: has()

Pass an array of keys, or several arguments, to require them all. Keys are looked up as they are, not as paths, so has("a.b") does not look inside a; the utilities list has the version that reads a path. A key that holds null still exists.

js
import { collect } from "@tolki/collection";

const order = collect({ account_id: 1, product: "Desk", amount: 5 });

order.has("product");
// => true

order.has(["product", "amount"]);
// => true

order.has(["amount", "price"]);
// => false

collect({ a: { b: 1 } }).has("a.b");
// => false

▶ Try it · collect(items).has(keys)

Resulttrue

hasAny ​

Determine whether any of the given keys exists in the collection.

Laravel: hasAny()

It looks keys up as they are, like has. The utilities list has the version that reads paths.

js
import { collect } from "@tolki/collection";

const order = collect({ account_id: 1, product: "Desk", amount: 5 });

order.hasAny(["product", "price"]);
// => true

order.hasAny(["name", "price"]);
// => false

▶ Try it · collect(items).hasAny(keys)

Resulttrue

hasMany ​

Determine whether the collection holds more than one item, optionally counting only the items that match.

Laravel: hasMany()

Pass a callback, or a key and a value, or a key, an operator and a value, to count only the matching items.

js
import { collect } from "@tolki/collection";

collect([]).hasMany();
// => false

collect(["1"]).hasMany();
// => false

collect([1, 2, 3]).hasMany();
// => true

collect([{ age: 2 }, { age: 3 }]).hasMany((item) => item.age === 2);
// => false

collect([{ age: 2 }, { age: 3 }]).hasMany("age", ">", 1);
// => true

▶ Try it · collect(items).hasMany(callback)

Resultfalse

hasSole ​

Determine whether the collection holds exactly one item, optionally counting only the items that match.

Laravel: hasSole()

It takes the same arguments as hasMany.

js
import { collect } from "@tolki/collection";

collect([]).hasSole();
// => false

collect(["1"]).hasSole();
// => true

collect([1, 2, 3]).hasSole((item) => item === 2);
// => true

collect([{ age: 2 }, { age: 3 }]).hasSole("age", 2);
// => true

▶ Try it · collect(items).hasSole(callback)

Resulttrue

implode ​

Join the items into a string.

Laravel: implode()

For arrays or objects, pass the key to join and the glue. For strings and numbers, pass the glue alone. A callback formats each item before it is joined.

js
import { collect } from "@tolki/collection";

const products = collect([
  { account_id: 1, product: "Desk" },
  { account_id: 2, product: "Chair" },
]);

products.implode("product", ", ");
// => "Desk, Chair"

products.implode((item, key) => item.product.toUpperCase(), ", ");
// => "DESK, CHAIR"

collect([1, 2, 3, 4, 5]).implode("-");
// => "1-2-3-4-5"

▶ Try it · collect(items).implode(glue)

Result"1-2-3-4-5"

intersect ​

Remove the values that are not in the given array or collection.

Laravel: intersect()

Only the values are compared, as strings, so 2 matches "2". Array and object items are matched by identity: see Differences from Laravel. The same operation on plain arrays and objects is in the utilities list.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

collect(["Desk", "Sofa", "Chair"])
  .intersect(["Desk", "Chair", "Bookcase"])
  .all();
// => ["Desk", "Chair"]

collect({ a: 1, b: 2 }).intersect({ x: 2 }).all();
// => { b: 2 }

collect([1, 2, 3]).intersect(["2"]).all();
// => [2]

▶ Try it · collect(items).intersect(other)

Result["Desk","Chair"]

intersectAssoc ​

Keep the key and value pairs that are present in the collection and in the given array or collection.

Laravel: intersectAssoc()

A pair stays only when both its key and its value match. Values are compared as strings, so 1 matches "1". The same operation on plain arrays and objects is in the utilities list.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

collect({ color: "red", size: "M", material: "cotton" })
  .intersectAssoc({ color: "blue", size: "M", material: "polyester" })
  .all();
// => { size: "M" }

collect([1, 2, 3]).intersectAssoc([1, 2, 9]).all();
// => [1, 2]

collect({ a: 1 }).intersectAssoc({ a: "1" }).all();
// => { a: 1 }

▶ Try it · collect(items).intersectAssoc(other)

Result{"size":"M"}

intersectAssocUsing ​

Keep the key and value pairs that are present in the collection and in the given items, comparing keys with a callback of your own.

Laravel: intersectAssocUsing()

The callback receives two keys and answers 0, or true, when they match. Values are compared as strings, so 1 matches "1". The same operation on plain arrays and objects is in the utilities list.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

const ignoreCase = (a, b) =>
  String(a).toLowerCase() === String(b).toLowerCase() ? 0 : 1;

collect({ color: "red", Size: "M", material: "cotton" })
  .intersectAssocUsing(
    { color: "blue", size: "M", material: "polyester" },
    ignoreCase,
  )
  .all();
// => { Size: "M" }

collect({ a: 1 }).intersectAssocUsing({ a: "1" }, ignoreCase).all();
// => { a: 1 }

▶ Try it · collect(items).intersectAssocUsing(other, callback)

Result{"Size":"M"}

intersectByKeys ​

Keep the items whose keys are present in the given array or collection.

Laravel: intersectByKeys()

Values are ignored. The same operation on plain arrays and objects is in the utilities list.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

collect({ serial: "UX301", type: "screen", year: 2009 })
  .intersectByKeys({ reference: "UX404", type: "tab", year: 2011 })
  .all();
// => { type: "screen", year: 2009 }

▶ Try it · collect(items).intersectByKeys(other)

Result{"type":"screen","year":2009}

intersectUsing ​

Remove the values that are not in the given array or collection, comparing the values with a callback of your own.

Laravel: intersectUsing()

The callback receives two values and answers 0, or true, when they match. The same operation on plain arrays and objects is in the utilities list.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

const ignoreCase = (a, b) => a.toLowerCase().localeCompare(b.toLowerCase());

collect(["Desk", "Sofa", "Chair"])
  .intersectUsing(["desk", "chair", "bookcase"], ignoreCase)
  .all();
// => ["Desk", "Chair"]

▶ Try it · collect(items).intersectUsing(other, callback)

Result["Desk","Chair"]

isEmpty ​

Determine whether the collection has no items.

Laravel: isEmpty()

js
import { collect } from "@tolki/collection";

collect([]).isEmpty();
// => true

collect([1, 2, 3]).isEmpty();
// => false

▶ Try it · collect(items).isEmpty()

Resulttrue

isNotEmpty ​

Determine whether the collection has at least one item.

Laravel: isNotEmpty()

js
import { collect } from "@tolki/collection";

collect([]).isNotEmpty();
// => false

collect([1, 2, 3]).isNotEmpty();
// => true

▶ Try it · collect(items).isNotEmpty()

Resulttrue

join ​

Join the items into a string, with a separate glue for the last item if you want one.

Laravel: join()

The second argument is placed before the last item. With one item, that item is returned as it is. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

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"

collect([]).join(", ", " and ");
// => ""

▶ Try it · collect(items).join(glue, finalGlue)

Result"a, b, and c"

jsonSerialize ​

Get the items in a form that JSON.stringify can encode.

A list, or a collection whose keys run 0..n-1 in order, gives an array. Any other keyed collection gives a record. Nested collections are converted too. See Keys and order for how a keyed collection holds integer keys.

js
import { collect } from "@tolki/collection";

collect([1, 2]).jsonSerialize();
// => [1, 2]

collect({ a: 1, b: 2 }).jsonSerialize();
// => { a: 1, b: 2 }

collect({ 0: "a", 1: "b" }).jsonSerialize();
// => ["a", "b"]

collect([collect([1]), { a: 1 }]).jsonSerialize();
// => [[1], { a: 1 }]

▶ Try it · collect(items).jsonSerialize()

Result["a","b"]

keyBy ​

Key the collection by a field of each item, or by what a callback returns.

Laravel: keyBy()

When several items give the same key, only the last one is kept. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

const products = collect([
  { product_id: "prod-100", name: "Desk" },
  { product_id: "prod-200", name: "Chair" },
]);

products.keyBy("product_id").all();
// => {
//   "prod-100": { product_id: "prod-100", name: "Desk" },
//   "prod-200": { product_id: "prod-200", name: "Chair" },
// }

products.keyBy((item) => item.product_id.toUpperCase()).all();
// => {
//   "PROD-100": { product_id: "prod-100", name: "Desk" },
//   "PROD-200": { product_id: "prod-200", name: "Chair" },
// }

▶ Try it · collect(items).keyBy(key)

Result{"prod-100":{"product_id":"prod-100","name":"Desk"},"prod-200":{"product_id":"prod-200","name":"Chair"}}

keys ​

Get the keys of the collection as a new collection.

Laravel: keys()

The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

collect({
  "prod-100": { product_id: "prod-100", name: "Desk" },
  "prod-200": { product_id: "prod-200", name: "Chair" },
})
  .keys()
  .all();
// => ["prod-100", "prod-200"]

collect(["a", "b", "c"]).keys().all();
// => [0, 1, 2]

▶ Try it · collect(items).keys()

Result["prod-100","prod-200"]

last ​

Get the last item, or the last item that passes a test.

Laravel: last()

With no match, last returns null, or the default you pass as the second argument, which may be a callback. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

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

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

collect([]).last();
// => null

collect([1, 2]).last((value) => value > 5, "none");
// => "none"

▶ Try it · collect(items).last(callback)

Result4

length ​

JS only

Get the number of items in the collection, as a property.

It gives the same number as count(), and lets code that reads length treat a collection like an array.

js
import { collect } from "@tolki/collection";

collect([1, 2, 3]).length;
// => 3

collect({ a: 1, b: 2 }).length;
// => 2

collect([]).length === 0;
// => true

▶ Try it · collect(items).length

Result3

make ​

Create a new collection from the given items.

Laravel: make()

The static make method does the same as collect(). Called on a subclass, it builds an instance of that subclass.

js
import { Collection } from "@tolki/collection";

Collection.make([1, 2, 3]).all();
// => [1, 2, 3]

Collection.make({ a: 1, b: 2 }).all();
// => { a: 1, b: 2 }

Collection.make(null).all();
// => []

▶ Try it · Collection.make(items)

Result[1,2,3]

map ​

Run a callback over every item and collect the results in a new collection.

Laravel: map()

The callback receives the value and the key, and the keys are kept. Like most collection methods, map returns a new collection and leaves the original as it was. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

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

collect({ a: 1, b: 2 })
  .map((value, key) => `${key}${value}`)
  .all();
// => { a: "a1", b: "b2" }

▶ Try it · collect(items).map(callback)

Result[2,4,6,8,10]

mapInto ​

Turn every item into a new instance of a class.

Laravel: mapInto()

The class constructor receives each value, and then its key. The example maps each instance to its code, so the result is readable.

js
import { collect } from "@tolki/collection";

class Currency {
  constructor(code) {
    this.code = code;
  }
}

collect(["USD", "EUR", "GBP"])
  .mapInto(Currency)
  .map((currency) => currency.code)
  .all();
// => ["USD", "EUR", "GBP"]

mapSpread ​

Run a callback over every nested row, passing the items of the row as separate arguments.

Laravel: mapSpread()

The key of the row comes after its items. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

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

collect([
  [1, "a"],
  [2, "b"],
])
  .mapSpread((number, letter, key) => `${number}${letter}${key}`)
  .all();
// => ["1a0", "2b1"]

▶ Try it · collect(items).mapSpread(callback)

Result[3,7]

mapToDictionary ​

Run a callback that gives one key and value pair for each item, and gather the values under their keys as arrays.

The callback returns an object with a single pair. Only its first pair is read, so a list it returns files its first value under key 0.

js
import { collect } from "@tolki/collection";

collect([
  { id: 1, name: "A" },
  { id: 2, name: "B" },
  { id: 3, name: "A" },
])
  .mapToDictionary((item) => ({ [item.name]: item.id }))
  .all();
// => { A: [1, 3], B: [2] }

collect([{ id: 1, name: "A" }])
  .mapToDictionary((item) => [item.name, item.id])
  .all();
// => { 0: ["A"] }

▶ Try it · collect(items).mapToDictionary(callback)

Result{"odd":[1,3],"even":[2,4]}

mapToGroups ​

Run a callback that gives one key and value pair for each item, and gather the values into collections under their keys.

Laravel: mapToGroups()

The callback returns an object with a single pair. Each group is a collection, so use .toArray() to read them all at once.

js
import { collect } from "@tolki/collection";

const grouped = collect([
  { name: "John Doe", department: "Sales" },
  { name: "Jane Doe", department: "Sales" },
  { name: "Johnny Doe", department: "Marketing" },
]).mapToGroups((item) => ({ [item.department]: item.name }));

grouped.toArray();
// => {
//   Sales: ["John Doe", "Jane Doe"],
//   Marketing: ["Johnny Doe"],
// }

grouped.get("Sales").all();
// => ["John Doe", "Jane Doe"]

▶ Try it · collect(items).mapToGroups(callback)

Result{"odd":[1,3],"even":[2,4]}

mapWithKeys ​

Run a callback that gives one key and value pair for each item, and build a collection from the pairs.

Laravel: mapWithKeys()

The callback returns an object with a single pair. When two items give the same key, the later one wins. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

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

▶ Try it · collect(items).mapWithKeys(callback)

Result{"n1":2,"n2":4,"n3":6}

max ​

Get the largest value, or the largest value at a key.

Laravel: max()

Pass a key or path, or a callback that gives the value to compare. null items are skipped, and an empty collection gives null.

js
import { collect } from "@tolki/collection";

collect([{ foo: 10 }, { foo: 20 }]).max("foo");
// => 20

collect([1, 2, 3, 4, 5]).max();
// => 5

collect([1, null, 3]).max();
// => 3

collect([]).max();
// => null

▶ Try it · collect(items).max(key)

Result20

median ​

Get the median of the values, or of the values at a key.

Laravel: median()

An odd count gives the middle value, and an even count the average of the two in the middle. null items are skipped, and a collection with nothing left gives null.

js
import { collect } from "@tolki/collection";

collect([{ foo: 10 }, { foo: 10 }, { foo: 20 }, { foo: 40 }]).median("foo");
// => 15

collect([1, 1, 2, 4]).median();
// => 1.5

collect([3, 1, 2]).median();
// => 2

collect([]).median();
// => null

▶ Try it · collect(items).median(key)

Result1.5

merge ​

Merge the given array or collection into the collection.

Laravel: merge()

A string key in the given items overwrites the same key in the collection. Integer keys are not matched: the given values are appended after the collection's own, and the result is renumbered.

js
import { collect } from "@tolki/collection";

collect({ product_id: 1, price: 100 })
  .merge({ price: 200, discount: false })
  .all();
// => { product_id: 1, price: 200, discount: false }

collect(["Desk", "Chair"]).merge(["Bookcase", "Door"]).all();
// => ["Desk", "Chair", "Bookcase", "Door"]

▶ Try it · collect(items).merge(other)

Result{"product_id":1,"price":200,"discount":false}

mergeRecursive ​

Merge the given array or collection into the collection, going down into the values they share.

Laravel: mergeRecursive()

When both sides hold a string key, their values are merged into an array, and arrays are merged again at every depth. Integer keys are appended.

js
import { collect } from "@tolki/collection";

collect({ product_id: 1, price: 100 })
  .mergeRecursive({ product_id: 2, price: 200, discount: false })
  .all();
// => { product_id: [1, 2], price: [100, 200], discount: false }

collect({ a: { b: 1 } })
  .mergeRecursive({ a: { c: 2 } })
  .all();
// => { a: { b: 1, c: 2 } }

collect({ a: { b: 1 } })
  .mergeRecursive({ a: { b: 2 } })
  .all();
// => { a: { b: [1, 2] } }

▶ Try it · collect(items).mergeRecursive(other)

Result{"product_id":[1,2],"price":[100,200],"discount":false}

min ​

Get the smallest value, or the smallest value at a key.

Laravel: min()

Pass a key or path, or a callback that gives the value to compare. null items are skipped, and an empty collection gives null.

js
import { collect } from "@tolki/collection";

collect([{ foo: 10 }, { foo: 20 }]).min("foo");
// => 10

collect([1, 2, 3, 4, 5]).min();
// => 1

collect([null]).min();
// => null

▶ Try it · collect(items).min(key)

Result10

mode ​

Get the value that appears most often, or the values at a key.

Laravel: mode()

The answer is always an array, because several values can tie. Tied values come in the order they first appear. null items are skipped, and a collection with nothing left gives null.

js
import { collect } from "@tolki/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]

collect([2, 2, 1, 1]).mode();
// => [2, 1]

collect([]).mode();
// => null

▶ Try it · collect(items).mode(key)

Result[1,2]

multiply ​

Repeat all the items the given number of times.

Laravel: multiply()

The result is a list. A fraction in the number is dropped, and 0 gives an empty collection.

js
import { collect } from "@tolki/collection";

collect([1, 2]).multiply(3).all();
// => [1, 2, 1, 2, 1, 2]

collect({ a: 1, b: 2 }).multiply(2).all();
// => [1, 2, 1, 2]

collect([1, 2]).multiply(2.5).all();
// => [1, 2, 1, 2]

collect([1, 2]).multiply(0).all();
// => []

▶ Try it · collect(items).multiply(multiplier)

Result[1,2,1,2,1,2]

nth ​

Take every n-th item, starting at an offset.

Laravel: nth()

The result is a list, whatever keys the items had. A step below 1 throws an InvalidArgumentException.

js
import { collect } from "@tolki/collection";

const letters = collect(["a", "b", "c", "d", "e", "f"]);

letters.nth(4).all();
// => ["a", "e"]

letters.nth(4, 1).all();
// => ["b", "f"]

collect([1, 2]).nth(0);
// => throws InvalidArgumentException

▶ Try it · collect(items).nth(step, offset)

Result["a","e"]

offsetExists ​

Determine whether an item exists at a key.

This is the method behind Laravel's isset($c['a']). An item that is null counts as absent. See Reading items.

js
import { collect } from "@tolki/collection";

collect([1, 2, 3]).offsetExists(1);
// => true

collect([1, 2, 3]).offsetExists(3);
// => false

collect({ a: null }).offsetExists("a");
// => false

▶ Try it · collect(items).offsetExists(key)

Resulttrue

offsetGet ​

Get the item at a key.

This is the method behind Laravel's $c['a']; a collection has no c.a or c[0]. A missing key gives undefined, where get takes a default. See Reading items.

js
import { collect } from "@tolki/collection";

collect([1, 2, 3]).offsetGet(1);
// => 2

collect({ a: 1, b: 2 }).offsetGet("a");
// => 1

collect({ a: 1, b: 2 }).offsetGet("c");
// => undefined

▶ Try it · collect(items).offsetGet(key)

Result1

offsetSet ​

Set the item at a key, or append it when the key is null.

This is the method behind Laravel's $c['a'] = 1 and $c[] = 1. See Reading items.

WARNING

Unlike most other collection methods, offsetSet does not return a new modified collection; it modifies the collection it is called on, and returns nothing.

js
import { collect } from "@tolki/collection";

const items = collect([1, 2]);

items.offsetSet(null, 3);

items.all();
// => [1, 2, 3]

items.offsetSet(1, 4);

items.all();
// => [1, 4, 3]

items.offsetSet(5, "x");

items.all();
// => { 0: 1, 1: 4, 2: 3, 5: "x" }

▶ Try it · collect(items).offsetSet(key, value)

Result[1,4]

offsetUnset ​

Remove the item at a key.

This is the method behind Laravel's unset($c['a']). A key that is not there changes nothing. See Reading items.

INFO

A list stays a list, so the items after the removed one move down a key. In Laravel they keep the keys they had. See Keys and order.

WARNING

Unlike most other collection methods, offsetUnset does not return a new modified collection; it modifies the collection it is called on, and returns nothing.

js
import { collect } from "@tolki/collection";

const items = collect([1, 2, 3]);

items.offsetUnset(1);

items.all();
// => [1, 3]

const keyed = collect({ a: 1, b: 2 });

keyed.offsetUnset("a");
// => undefined

keyed.all();
// => { b: 2 }

keyed.offsetUnset("missing");

keyed.all();
// => { b: 2 }

▶ Try it · collect(items).offsetUnset(key)

Result[1,3]

only ​

Get the items with the given keys.

Laravel: only()

Pass the keys as an array or a collection, or as separate arguments. Each key is taken as it is, so "a.b" does not reach a nested value. A key the collection lacks is skipped, and null returns every item. For the inverse, see except. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

collect({ product_id: 1, name: "Desk", price: 100, discount: false })
  .only(["product_id", "name"])
  .all();
// => { product_id: 1, name: "Desk" }

collect({ a: 1, b: 2, c: 3 }).only("a", "c").all();
// => { a: 1, c: 3 }

collect([1, 2, 3]).only(0, 2).all();
// => [1, 3]

collect({ a: { b: 1 } })
  .only("a.b")
  .all();
// => {}

collect({ a: 1, b: 2 }).only(null).all();
// => { a: 1, b: 2 }

▶ Try it · collect(items).only(keys)

Result{"product_id":1,"name":"Desk"}

pad ​

Fill the collection with a value until it reaches a size.

Laravel: pad()

A positive size pads at the end, and a negative size pads at the beginning. Nothing is added when the size, ignoring its sign, is no more than the number of items. When the collection grows, its integer keys are renumbered from 0 in order, pad slots included, and its string keys are kept. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

const letters = collect(["A", "B", "C"]);

letters.pad(5, 0).all();
// => ["A", "B", "C", 0, 0]

letters.pad(-5, 0).all();
// => [0, 0, "A", "B", "C"]

letters.pad(2, 0).all();
// => ["A", "B", "C"]

collect({ a: 1, b: 2 }).pad(-4, 0).all();
// => { 0: 0, 1: 0, a: 1, b: 2 }

▶ Try it · collect(items).pad(size, value)

Result["A","B","C",0,0]

partition ​

Separate the items that pass a truth test from those that do not.

Laravel: partition()

The result is a collection of two collections: the items that pass, then the rest. Destructure it, or read [0] and [1]. Pass a callback, a key to test for truthiness, or a key with an operator and a value, as where does. The same operation on plain arrays and objects is in the utilities list.

INFO

A list stays a list, so each half is renumbered from 0. In Laravel each half keeps the keys its items had. See Keys and order.

js
import { collect } from "@tolki/collection";

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

underThree.all();
// => [1, 2]

equalOrAboveThree.all();
// => [3, 4, 5, 6]

const [active, inactive] = collect([
  { name: "Ann", active: true },
  { name: "Ben", active: false },
]).partition("active");

active.toArray();
// => [{ name: "Ann", active: true }]

inactive.toArray();
// => [{ name: "Ben", active: false }]

const [adults] = collect([{ age: 12 }, { age: 30 }]).partition("age", ">", 18);

adults.toArray();
// => [{ age: 30 }]

▶ Try it · collect(items).partition(callback)

Result[[3,4,5,6],[1,2]]

percentage ​

Get the percentage of items that pass a truth test.

Laravel: percentage()

The answer is rounded to two decimal places. Pass a precision as the second argument to change that. An empty collection gives null.

js
import { collect } from "@tolki/collection";

const numbers = collect([1, 1, 2, 2, 2, 3]);

numbers.percentage((value) => value === 1);
// => 33.33

numbers.percentage((value) => value === 1, 3);
// => 33.333

numbers.percentage((value) => value === 1, 0);
// => 33

collect([]).percentage((value) => value === 1);
// => null

▶ Try it · collect(items).percentage(callback, precision)

Result50

pipe ​

Pass the collection to a callback and return what the callback returns.

Laravel: pipe()

The result can be any value, not only a collection.

js
import { collect } from "@tolki/collection";

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

collect([1, 2, 3]).pipe((collection) => collection.count());
// => 3

▶ Try it · collect(items).pipe(callback)

Result6

pipeInto ​

Create a new instance of a class, passing the collection to its constructor.

Laravel: pipeInto()

Unlike mapInto, which makes one instance per item, pipeInto makes one instance from the whole collection.

js
import { collect } from "@tolki/collection";

class ResourceCollection {
  constructor(collection) {
    this.collection = collection;
  }
}

const resource = collect([1, 2, 3]).pipeInto(ResourceCollection);

resource instanceof ResourceCollection;
// => true

resource.collection.all();
// => [1, 2, 3]

pipeThrough ​

Pass the collection through a list of callbacks and return the last result.

Laravel: pipeThrough()

The first callback receives the collection, and each one after it receives what the one before it returned.

An empty list returns the collection itself, as it does in Laravel.

js
import { collect } from "@tolki/collection";

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

const items = collect([1, 2, 3]);

items.pipeThrough([]) === items;
// => true

▶ Try it · collect(items).pipeThrough(callbacks)

Result15

pluck ​

Get the values of a key from every item.

Laravel: pluck()

Pass a second argument to key the result by another field. If several items give the same key, the last one wins. The key can be a path in "dot" notation, with * for every element of a list: see Dot Notation and Wildcards. Either argument can be a callback that receives the item instead. An item without the key gives null. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

const products = collect([
  { product_id: "prod-100", name: "Desk" },
  { product_id: "prod-200", name: "Chair" },
]);

products.pluck("name").all();
// => ["Desk", "Chair"]

products.pluck("name", "product_id").all();
// => { "prod-100": "Desk", "prod-200": "Chair" }

collect([
  { brand: "Tesla", color: "red" },
  { brand: "Pagani", color: "white" },
  { brand: "Tesla", color: "black" },
  { brand: "Pagani", color: "orange" },
])
  .pluck("color", "brand")
  .all();
// => { Tesla: "black", Pagani: "orange" }

collect([
  { name: "Laracon", speakers: { first_day: ["Rosa", "Judith"] } },
  { name: "VueConf", speakers: { first_day: ["Abigail", "Joey"] } },
])
  .pluck("speakers.first_day")
  .all();
// => [["Rosa", "Judith"], ["Abigail", "Joey"]]

collect([{ tags: [{ id: 1 }, { id: 2 }] }, { tags: [{ id: 3 }] }])
  .pluck("tags.*.id")
  .all();
// => [[1, 2], [3]]

collect([{ name: "Desk" }])
  .pluck((item) => item.name.toUpperCase())
  .all();
// => ["DESK"]

collect([{ name: "Desk" }, { price: 5 }])
  .pluck("name")
  .all();
// => ["Desk", null]

▶ Try it · collect(items).pluck(value, key)

Result{"prod-100":"Desk","prod-200":"Chair"}

pop ​

Remove and return the last item, or the last several items.

Laravel: pop()

Without a count, pop returns the last item, or null for an empty collection. A count of 1 does the same. A count of 2 or more returns a new collection of that many items from the end, last first, and a count of 0 or below returns an empty collection and removes nothing. The same operation on plain arrays and objects is in the utilities list.

WARNING

Unlike most other collection methods, pop does not return a new modified collection; it modifies the collection it is called on, and returns the item or items it removed.

js
import { collect } from "@tolki/collection";

const items = collect([1, 2, 3, 4, 5]);

items.pop();
// => 5

items.all();
// => [1, 2, 3, 4]

items.pop(3).all();
// => [4, 3, 2]

items.all();
// => [1]

items.pop(1);
// => 1

items.pop(0).all();
// => []

items.pop(-1).all();
// => []

items.all();
// => []

collect([]).pop();
// => null

▶ Try it · collect(items).pop(count)

Result{"popped":[5,4],"left":[1,2,3]}

prepend ​

Add an item to the beginning of the collection.

Laravel: prepend()

Pass a second argument to give the item a key. The same operation on plain arrays and objects is in the utilities list, where it returns a new value and leaves the original unchanged.

A null or undefined key files the item under the empty string "", as it does in Laravel.

WARNING

Unlike most other collection methods, prepend does not return a new modified collection; it modifies and returns the collection it is called on.

js
import { collect } from "@tolki/collection";

const numbers = collect([1, 2, 3, 4, 5]);

numbers.prepend(0).all();
// => [0, 1, 2, 3, 4, 5]

numbers.all();
// => [0, 1, 2, 3, 4, 5]

collect({ one: 1, two: 2 }).prepend(0, "zero").all();
// => { zero: 0, one: 1, two: 2 }

collect([1]).prepend(0, null).keys().all();
// => ["", 0]

▶ Try it · collect(items).prepend(value, key)

Result{"zero":0,"one":1,"two":2}

pull ​

Remove an item by key and return it.

Laravel: pull()

The second argument is returned when the key is missing; it may be a callback. A key with dots reaches into nested arrays and objects, and removes the value there. The same operation on plain arrays and objects is in the utilities list, where it returns a new value and leaves the original unchanged.

INFO

A list stays a list, so the items after the removed one move down a key. In Laravel they keep the keys they had. See Keys and order.

WARNING

Unlike most other collection methods, pull does not return a new modified collection; it modifies the collection it is called on, and returns the item it removed.

js
import { collect } from "@tolki/collection";

const product = collect({ product_id: "prod-100", name: "Desk" });

product.pull("name");
// => "Desk"

product.all();
// => { product_id: "prod-100" }

product.pull("price", 0);
// => 0

collect({ a: { b: 1, c: 2 } }).pull("a.b");
// => 1

const prices = collect([10, 20, 30, 40]);

prices.pull(1);
// => 20

prices.all();
// => [10, 30, 40]

▶ Try it · collect(items).pull(key, defaultValue)

Result{"pulled":"Desk","left":{"product_id":"prod-100"}}

push ​

Add one or more items to the end of the collection.

Laravel: push()

On a keyed collection, each item is stored under the next free integer key. The same operation on plain arrays and objects is in the utilities list, where it returns a new value and leaves the original unchanged.

WARNING

Unlike most other collection methods, push does not return a new modified collection; it modifies and returns the collection it is called on.

js
import { collect } from "@tolki/collection";

const numbers = collect([1, 2, 3, 4]);

numbers.push(5).all();
// => [1, 2, 3, 4, 5]

numbers.push(6, 7).all();
// => [1, 2, 3, 4, 5, 6, 7]

numbers.all();
// => [1, 2, 3, 4, 5, 6, 7]

collect({ a: 1 }).push(2).all();
// => { 0: 2, a: 1 }

▶ Try it · collect(items).push(value)

Result[1,2,3,4,5]

put ​

Set the item at a key.

Laravel: put()

The key is added when it is new and overwritten when it exists. On a list, put at the next integer key appends, and any other key makes the collection keyed. See Keys and order.

WARNING

Unlike most other collection methods, put does not return a new modified collection; it modifies and returns the collection it is called on.

js
import { collect } from "@tolki/collection";

const product = collect({ product_id: 1, name: "Desk" });

product.put("price", 100).all();
// => { product_id: 1, name: "Desk", price: 100 }

product.put("name", "Chair").all();
// => { product_id: 1, name: "Chair", price: 100 }

product.all();
// => { product_id: 1, name: "Chair", price: 100 }

collect([1, 2]).put(2, 3).all();
// => [1, 2, 3]

▶ Try it · collect(items).put(key, value)

Result{"product_id":1,"name":"Desk","price":100}

random ​

Get one random item, or several.

Laravel: random()

Without an argument, random returns one item. With a count, it returns a collection of that many items, and it throws an InvalidArgumentException when the collection has fewer. The count can be a callback that receives the collection and returns the count. The picked items come back as a list; pass true as the second argument to keep their keys, which Keys and order explains. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

const numbers = collect([1, 2, 3, 4, 5]);

numbers.random();
// e.g. 4

[1, 2, 3, 4, 5].includes(numbers.random());
// => true

numbers.random(3).all();
// e.g. [2, 4, 5]

numbers.random(3).count();
// => 3

numbers.random((items) => Math.min(10, items.count())).count();
// => 5

numbers.random(6);
// => throws InvalidArgumentException

collect({ a: 1, b: 2, c: 3 }).random(2).keys().all();
// => [0, 1]

collect({ a: 1, b: 2, c: 3 }).random(2, true).count();
// => 2

range ​

Create a collection of numbers between two values.

Laravel: range()

The static range method counts from the first number to the second, including both. It counts down when the second number is lower. A third argument sets the step, which is always positive on an increasing range and may be negative on a decreasing one. It throws an Error for a step of 0, a negative step on an increasing range, or a step larger than the range. Laravel's docs call range on an instance, as collect()->range(3, 6). Here it is static only.

js
import { Collection } from "@tolki/collection";

Collection.range(3, 6).all();
// => [3, 4, 5, 6]

Collection.range(1, 10, 2).all();
// => [1, 3, 5, 7, 9]

Collection.range(5, 1).all();
// => [5, 4, 3, 2, 1]

Collection.range(0, 1, 0.25).all();
// => [0, 0.25, 0.5, 0.75, 1]

Collection.range(1, 5, 0);
// => throws Error

▶ Try it · Collection.range(from, to, step)

Result[3,4,5,6]

reduce ​

Reduce the collection to a single value.

Laravel: reduce()

The callback receives the result of the last call, the item and its key, and returns the new result. Pass a second argument for the starting result. Without one, the first call receives null, so the first item reaches the callback too, unlike Array.prototype.reduce. An empty collection gives the starting result, or null without one.

js
import { collect } from "@tolki/collection";

const numbers = collect([1, 2, 3]);

numbers.reduce((carry, item) => carry + item, 0);
// => 6

numbers.reduce((carry, item) => carry + item, 4);
// => 10

numbers.reduce((carry, item) => (carry ?? 0) + item);
// => 6

collect([]).reduce((carry, item) => carry + item);
// => null

const ratio = { usd: 1, gbp: 1.37, eur: 1.22 };

collect({ usd: 1400, gbp: 1200, eur: 1000 }).reduce(
  (carry, value, key) => carry + value * ratio[key],
  0,
);
// => 4264

▶ Try it · collect(items).reduce(callback, initial)

Result6

reduceInto ​

Reduce the collection into a starting value by changing that value.

Laravel: reduceInto()

Unlike reduce, the callback need not return the result. It receives the starting value, the item and its key, and changes the starting value in place. reduceInto returns the starting value.

JavaScript cannot change a number or a string in place, so the callback may return the new value instead. Returning nothing keeps the current one. See JavaScript-only additions.

js
import { collect } from "@tolki/collection";

class OrderStats {
  total = 0;
  count = 0;
}

const orders = collect([{ amount: 100 }, { amount: 250 }, { amount: 50 }]);

const stats = orders.reduceInto(new OrderStats(), (stats, order) => {
  stats.total += order.amount;
  stats.count++;
});

stats.total;
// => 400

stats.count;
// => 3

collect([1, 2, 3, 4, 5]).reduceInto([], (result, value) => {
  if (value % 2 === 0) {
    result.push(value);
  }
});
// => [2, 4]

collect([1, 2, 3, 4, 5]).reduceInto(0, (total, value) => total + value);
// => 15

▶ Try it · collect(items).reduceInto(initial, callback)

Result15

reduceSpread ​

Reduce the collection to several values at once.

Laravel: reduceSpread()

Pass the starting values after the callback. The callback receives those values, then the item and its key, and must return an array with the next values. reduceSpread returns the final array. It throws an UnexpectedValueException when the callback returns anything else.

js
import { collect } from "@tolki/collection";

const costs = collect([5, 6, 2]);

const [creditsRemaining, batch] = costs.reduceSpread(
  (credits, batch, cost) => {
    if (credits >= cost) {
      batch.push(cost);
      credits -= cost;
    }

    return [credits, batch];
  },
  8,
  [],
);

creditsRemaining;
// => 1

batch;
// => [5, 2]

collect([1]).reduceSpread(() => false, 0);
// => throws UnexpectedValueException

▶ Try it · collect(items).reduceSpread(callback, ...initial)

Result[6,3]

reduceWithKeys ​

Reduce a keyed collection to a single value.

It does what reduce does, which already hands the callback each item's key.

js
import { collect } from "@tolki/collection";

collect({ a: 1, b: 2 }).reduceWithKeys(
  (carry, value, key) => carry + key + value,
  "",
);
// => "a1b2"

collect([1, 2, 3]).reduceWithKeys((carry, value) => carry + value, 0);
// => 6

▶ Try it · collect(items).reduceWithKeys(callback, initial)

Result"a1b2"

reject ​

Remove the items that pass a truth test.

Laravel: reject()

The callback receives the item and its key, and the items it answers truthy for are removed. Pass a value instead to remove each item equal to it, compared loosely (see Loose and strict comparison). With no argument, reject removes every item that is truthy by PHP's rules. For the inverse, see filter. The same operation on plain arrays and objects is in the utilities list.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

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

collect([1, 2, 3, 2]).reject(2).all();
// => [1, 3]

collect([1, null, 2, false, 3, ""]).reject().all();
// => [null, false, ""]

collect({ a: 1, b: 2, c: 3 })
  .reject((value, key) => key === "b")
  .all();
// => { a: 1, c: 3 }

▶ Try it · collect(items).reject(callback)

Result[1,2]

replace ​

Replace items by key.

Laravel: replace()

replace works like merge, but it also overwrites items with matching integer keys. It returns a new collection, and a key the original lacks is added. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

const names = collect(["Taylor", "Abigail", "James"]);

names.replace({ 1: "Victoria", 3: "Finn" }).all();
// => ["Taylor", "Victoria", "James", "Finn"]

names.all();
// => ["Taylor", "Abigail", "James"]

collect({ name: "amir", family: "otwell" })
  .replace({ name: "taylor", age: 26 })
  .all();
// => { name: "taylor", family: "otwell", age: 26 }

▶ Try it · collect(items).replace(replacement)

Result["Taylor","Victoria","James","Finn"]

replaceRecursive ​

Replace items by key, going into nested arrays and objects.

Laravel: replaceRecursive()

replaceRecursive works like replace, but it goes into nested arrays and objects and applies the same replacement to the inner values. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

collect(["Taylor", "Abigail", ["James", "Victoria", "Finn"]])
  .replaceRecursive({ 0: "Charlie", 2: { 1: "King" } })
  .all();
// => ["Charlie", "Abigail", ["James", "King", "Finn"]]

collect({ a: { b: 1 } })
  .replaceRecursive({ a: { c: 2 } })
  .all();
// => { a: { b: 1, c: 2 } }

▶ Try it · collect(items).replaceRecursive(replacement)

Result{"a":{"b":1,"c":2}}

reverse ​

Reverse the order of the items.

Laravel: reverse()

It returns a new collection. The same operation on plain arrays and objects is in the utilities list.

INFO

Integer keys are renumbered from 0 in the new order and string keys are kept, where Laravel keeps every key. See Keys and order.

js
import { collect } from "@tolki/collection";

const letters = collect(["a", "b", "c", "d", "e"]);

letters.reverse().all();
// => ["e", "d", "c", "b", "a"]

letters.reverse().keys().all();
// => [0, 1, 2, 3, 4]

letters.all();
// => ["a", "b", "c", "d", "e"]

collect({ a: 1, b: 2, c: 3 }).reverse().all();
// => { c: 3, b: 2, a: 1 }

▶ Try it · collect(items).reverse()

Result["e","d","c","b","a"]

Find the key of the first item that matches a value.

Laravel: search()

It returns the key of the match, or false when nothing matches. The search is loose by default, so "4" finds 4 (see Loose and strict comparison). Pass true as the second argument to compare strictly, or pass a callback to find the first item that passes a test. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

const numbers = collect([2, 4, 6, 8]);

numbers.search(4);
// => 1

numbers.search("4");
// => 1

numbers.search("4", true);
// => false

numbers.search((item, key) => item > 5);
// => 2

collect({ a: 1, b: 2 }).search(2);
// => "b"

▶ Try it · collect(items).search(value, strict)

Result1

select ​

Keep only the given keys of each item.

Laravel: select()

It works like an SQL SELECT: where only picks items by their key in the collection, select picks keys inside every item. Pass the keys as an array or a collection, or as separate arguments. A key an item lacks is skipped. The keys are exact, not paths, so "details.age" does not reach into details, and Laravel does the same. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

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" },
// ]

users.select("name").all();
// => [{ name: "Taylor Otwell" }, { name: "Victoria Faith" }]

collect({ a: { id: 1, name: "x" }, b: { id: 2, name: "y" } })
  .select("id")
  .all();
// => { a: { id: 1 }, b: { id: 2 } }

collect([{ id: 1, details: { age: 30 } }])
  .select(["id", "details.age"])
  .all();
// => [{ id: 1 }]

▶ Try it · collect(items).select(keys)

Result[{"name":"Taylor Otwell","role":"Developer"},{"name":"Victoria Faith","role":"Researcher"}]

shift ​

Remove and return the first item, or the first several items.

Laravel: shift()

Without a count, shift returns the first item, or null for an empty collection. A count of 1 does the same. A count of 2 or more returns a new collection of that many items from the start, and a count of 0 returns an empty collection and removes nothing. A negative count throws an InvalidArgumentException. The same operation on plain arrays and objects is in the utilities list.

WARNING

Unlike most other collection methods, shift does not return a new modified collection; it modifies the collection it is called on, and returns the item or items it removed.

js
import { collect } from "@tolki/collection";

const items = collect([1, 2, 3, 4, 5]);

items.shift();
// => 1

items.all();
// => [2, 3, 4, 5]

items.shift(3).all();
// => [2, 3, 4]

items.all();
// => [5]

items.shift(1);
// => 5

items.shift(0).all();
// => []

collect([]).shift();
// => null

collect([1]).shift(-1);
// => throws InvalidArgumentException

▶ Try it · collect(items).shift(count)

Result{"shifted":[1,2],"left":[3,4,5]}

shuffle ​

Put the items in a random order.

Laravel: shuffle()

It returns a new collection and leaves the original as it was. The result is a list, whatever keys the items had. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

const numbers = collect([1, 2, 3, 4, 5]);

numbers.shuffle().all();
// e.g. [3, 2, 5, 1, 4]

numbers.shuffle().sort().all();
// => [1, 2, 3, 4, 5]

numbers.all();
// => [1, 2, 3, 4, 5]

collect({ a: 1, b: 2, c: 3 }).shuffle().keys().all();
// => [0, 1, 2]

skip ​

Remove the given number of items from the beginning.

Laravel: skip()

It returns a new collection. A count above the number of items gives an empty collection.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

const numbers = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

numbers.skip(4).all();
// => [5, 6, 7, 8, 9, 10]

collect([1, 2]).skip(5).all();
// => []

collect({ a: 1, b: 2, c: 3 }).skip(1).all();
// => { b: 2, c: 3 }

▶ Try it · collect(items).skip(count)

Result[5,6,7,8,9,10]

skipUntil ​

Skip items until one passes a test or equals a value.

Laravel: skipUntil()

Pass a callback, which receives the item and its key, or a value. A value is compared strictly, so "3" does not match 3. The item that stops the skipping and every item after it are returned. If nothing stops it, the result is an empty collection. The same operation on plain arrays and objects is in the utilities list.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

const numbers = collect([1, 2, 3, 4]);

numbers.skipUntil((item) => item >= 3).all();
// => [3, 4]

numbers.skipUntil(3).all();
// => [3, 4]

numbers.skipUntil("3").all();
// => []

numbers.skipUntil(9).all();
// => []

collect({ a: 1, b: 2, c: 3 })
  .skipUntil((value, key) => key === "b")
  .all();
// => { b: 2, c: 3 }

▶ Try it · collect(items).skipUntil(callback)

Result[3,4]

skipWhile ​

Skip items while a test passes or a value matches.

Laravel: skipWhile()

Pass a callback, which receives the item and its key, or a value. A value is compared strictly, so "1" does not match 1. The first item that fails the test and every item after it are returned. If the test never fails, the result is an empty collection. The same operation on plain arrays and objects is in the utilities list.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

const numbers = collect([1, 2, 3, 4]);

numbers.skipWhile((item) => item <= 3).all();
// => [4]

collect([1, 1, 2, 1]).skipWhile(1).all();
// => [2, 1]

collect([1, 1, 2]).skipWhile("1").all();
// => [1, 1, 2]

numbers.skipWhile(() => true).all();
// => []

collect({ a: 1, b: 2, c: 3 })
  .skipWhile((value, key) => key === "a")
  .all();
// => { b: 2, c: 3 }

▶ Try it · collect(items).skipWhile(callback)

Result[3,4]

slice ​

Get a slice of the collection, starting at the given offset.

Laravel: slice()

Pass a length as the second argument to limit the size of the slice. A negative offset counts from the end. A negative length stops that many items before the end. The same operation on plain arrays and objects is in the utilities list.

INFO

A list stays a list, so the slice is renumbered from 0. In Laravel the items keep the keys they had, which is why its docs call values after slicing. See Keys and order.

js
import { collect } from "@tolki/collection";

const numbers = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

numbers.slice(4).all();
// => [5, 6, 7, 8, 9, 10]

numbers.slice(4, 2).all();
// => [5, 6]

numbers.slice(-2).all();
// => [9, 10]

numbers.slice(2, -5).all();
// => [3, 4, 5]

collect({ a: 1, b: 2, c: 3 }).slice(1).all();
// => { b: 2, c: 3 }

▶ Try it · collect(items).slice(offset, length)

Result[5,6]

sliding ​

Create chunks representing a "sliding window" view of the items.

Laravel: sliding()

Each window holds size items (2 by default), and each starts step items (1 by default) after the one before. A size or step below 1 throws an InvalidArgumentException. If the collection holds fewer items than one window, the result is empty. The windows of a keyed collection keep its keys. It pairs well with eachSpread and mapSpread, which hand each window to a callback as separate arguments.

INFO

A list stays a list, so each window is renumbered from 0. In Laravel a window keeps the keys its items had. See Keys and order.

js
import { collect } from "@tolki/collection";

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

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

collect({ a: 1, b: 2, c: 3 }).sliding().toArray();
// => [{ a: 1, b: 2 }, { b: 2, c: 3 }]

collect([1, 2, 4, 7, 11])
  .sliding()
  .mapSpread((previous, current) => current - previous)
  .all();
// => [1, 2, 3, 4]

collect([1, 2, 3]).sliding(5).toArray();
// => []

collect([1, 2, 3]).sliding(0);
// => throws InvalidArgumentException

▶ Try it · collect(items).sliding(size, step)

Result[[1,2],[2,3],[3,4],[4,5]]

sole ​

Get the first item that passes a test, but only if exactly one item does.

Laravel: sole()

Pass a callback, or a key and a value to look for a matching pair (an operator may sit between them, as in sole("price", ">", 150)). With no argument it returns the only item in the collection. It throws an ItemNotFoundException when no item matches and a MultipleItemsFoundException when several do. To check without throwing, use hasSole.

js
import { collect } from "@tolki/collection";

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

collect([
  { product: "Desk", price: 200 },
  { product: "Chair", price: 100 },
]).sole("product", "Chair");
// => { product: "Chair", price: 100 }

collect([{ product: "Desk", price: 200 }]).sole();
// => { product: "Desk", price: 200 }

collect([1, 2]).sole((value) => value > 5);
// => throws ItemNotFoundException

collect([1, 2]).sole();
// => throws MultipleItemsFoundException

▶ Try it · collect(items).sole(key, value)

Result{"product":"Chair","price":100}

some ​

Alias for the contains method.

Laravel: some()

The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

collect([1, 2, 3]).some(2);
// => true

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

collect([1, 2, 3]).some("2");
// => true

▶ Try it · collect(items).some(value)

Resulttrue

sort ​

Sort the collection, smallest first.

Laravel: sort()

It returns a new collection and leaves the original as it was. To use your own order, pass a callback that takes two items and returns a number below, equal to or above zero. To sort rows by a field, use sortBy, and to sort in the opposite order, use sortDesc. The same operation on plain arrays and objects is in the utilities list.

INFO

Integer keys are renumbered from 0 in the new order and string keys are kept, where Laravel keeps every key. See Keys and order.

js
import { collect } from "@tolki/collection";

const numbers = collect([5, 3, 1, 2, 4]);

numbers.sort().all();
// => [1, 2, 3, 4, 5]

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

numbers.all();
// => [5, 3, 1, 2, 4]

collect({ a: 3, b: 1, c: 2 }).sort().all();
// => { b: 1, c: 2, a: 3 }

▶ Try it · collect(items).sort(callback)

Result[1,2,3,4,5]

sortBy ​

Sort the collection by a key, by the result of a callback, or by several keys.

Laravel: sortBy()

A key may be a dot-notation path. Pass true as the second argument to sort in descending order. To sort by several fields, pass a list of [key, direction] pairs, where the direction is "asc" or "desc", or a list of callbacks that compare two items. PHP's sort flags are not supported (see Not portable).

INFO

Integer keys are renumbered from 0 in the new order and string keys are kept, where Laravel keeps every key. See Keys and order.

js
import { collect } from "@tolki/collection";

const products = collect([
  { name: "Desk", price: 200 },
  { name: "Chair", price: 100 },
  { name: "Bookcase", price: 150 },
]);

products.sortBy("price").all();
// => [
//   { name: "Chair", price: 100 },
//   { name: "Bookcase", price: 150 },
//   { name: "Desk", price: 200 },
// ]

products.sortBy("price", true).all();
// => [
//   { name: "Desk", price: 200 },
//   { name: "Bookcase", price: 150 },
//   { name: "Chair", price: 100 },
// ]

products
  .sortBy((product) => product.name.length)
  .pluck("name")
  .all();
// => ["Desk", "Chair", "Bookcase"]

const people = collect([
  { name: "Taylor Otwell", age: 34 },
  { name: "Abigail Otwell", age: 30 },
  { name: "Taylor Otwell", age: 36 },
  { name: "Abigail Otwell", age: 32 },
]);

people
  .sortBy([
    ["name", "asc"],
    ["age", "desc"],
  ])
  .pluck("age")
  .all();
// => [32, 30, 36, 34]

people
  .sortBy([(a, b) => a.name.localeCompare(b.name), (a, b) => b.age - a.age])
  .pluck("age")
  .all();
// => [32, 30, 36, 34]

▶ Try it · collect(items).sortBy(key, descending)

Result[{"name":"Chair","price":100},{"name":"Bookcase","price":150},{"name":"Desk","price":200}]

sortByDesc ​

Sort the collection by a key or callback, largest first.

Laravel: sortByDesc()

It takes the same first argument as sortBy and sorts in the opposite order. When that argument is a list of [key, direction] pairs or callbacks, each one sorts descending.

INFO

Integer keys are renumbered from 0 in the new order and string keys are kept, where Laravel keeps every key. See Keys and order.

js
import { collect } from "@tolki/collection";

const products = collect([
  { name: "Desk", price: 200 },
  { name: "Chair", price: 100 },
  { name: "Bookcase", price: 150 },
]);

products.sortByDesc("price").pluck("name").all();
// => ["Desk", "Bookcase", "Chair"]

products
  .sortByDesc((product) => product.name.length)
  .pluck("name")
  .all();
// => ["Bookcase", "Chair", "Desk"]

▶ Try it · collect(items).sortByDesc(key)

Result[{"name":"Desk","price":200},{"name":"Bookcase","price":150},{"name":"Chair","price":100}]

sortDesc ​

Sort the collection, largest first.

Laravel: sortDesc()

It is the opposite of sort. Unlike sort, it takes no callback. To use your own order, call sort and invert the comparison. The same operation on plain arrays and objects is in the utilities list.

INFO

Integer keys are renumbered from 0 in the new order and string keys are kept, where Laravel keeps every key. See Keys and order.

js
import { collect } from "@tolki/collection";

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

collect({ a: 1, b: 3, c: 2 }).sortDesc().all();
// => { b: 3, c: 2, a: 1 }

▶ Try it · collect(items).sortDesc()

Result[5,4,3,2,1]

sortKeys ​

Sort the collection by its keys.

Laravel: sortKeys()

Pass true to sort in descending order. See sortKeysDesc and sortKeysUsing.

INFO

Integer keys are renumbered from 0 in the new order and string keys are kept, where Laravel keeps every key. See Keys and order.

js
import { collect } from "@tolki/collection";

collect({ id: 22345, first: "John", last: "Doe" }).sortKeys().all();
// => { first: "John", id: 22345, last: "Doe" }

collect({ id: 22345, first: "John", last: "Doe" }).sortKeys(true).all();
// => { last: "Doe", id: 22345, first: "John" }

collect({ 5: "e", 2: "b", 9: "z" }).sortKeys().all();
// => { 0: "b", 1: "e", 2: "z" }

▶ Try it · collect(items).sortKeys(descending)

Result{"first":"John","id":22345,"last":"Doe"}

sortKeysDesc ​

Sort the collection by its keys, largest first.

Laravel: sortKeysDesc()

It has the same signature as sortKeys and sorts in the opposite order.

INFO

Integer keys are renumbered from 0 in the new order and string keys are kept, where Laravel keeps every key. See Keys and order.

js
import { collect } from "@tolki/collection";

collect({ id: 22345, first: "John", last: "Doe" }).sortKeysDesc().all();
// => { last: "Doe", id: 22345, first: "John" }

collect({ 5: "e", 2: "b", 9: "z" }).sortKeysDesc().all();
// => { 0: "z", 1: "e", 2: "b" }

▶ Try it · collect(items).sortKeysDesc()

Result{"last":"Doe","id":22345,"first":"John"}

sortKeysUsing ​

Sort the collection by its keys, using a callback.

Laravel: sortKeysUsing()

The callback takes two keys and returns a number below, equal to or above zero.

INFO

Integer keys are renumbered from 0 in the new order and string keys are kept, where Laravel keeps every key. See Keys and order.

js
import { collect } from "@tolki/collection";

collect({ ID: 22345, first: "John", last: "Doe" })
  .sortKeysUsing((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()))
  .all();
// => { first: "John", ID: 22345, last: "Doe" }

collect({ b: 2, a: 1, c: 3 })
  .sortKeysUsing((a, b) => b.localeCompare(a))
  .all();
// => { c: 3, b: 2, a: 1 }

▶ Try it · collect(items).sortKeysUsing(callback)

Result{"first":"John","ID":22345,"last":"Doe"}

splice ​

Remove a slice of the items and return it, optionally putting new items in its place.

Laravel: splice()

The first argument is the index to start at, and a negative one counts from the end. The second limits how many items are removed, and without it everything from the index on goes. A third argument holds the items to insert in place of the removed ones, and a single value that is not a list becomes one item. The same operation on plain arrays and objects is in the utilities list.

WARNING

Unlike most other collection methods, splice does not return a new modified collection; it modifies the collection it is called on, and returns a new collection of the items it removed.

js
import { collect } from "@tolki/collection";

const items = collect([1, 2, 3, 4, 5]);

items.splice(2).all();
// => [3, 4, 5]

items.all();
// => [1, 2]

const more = collect([1, 2, 3, 4, 5]);

more.splice(2, 1).all();
// => [3]

more.all();
// => [1, 2, 4, 5]

const inserted = collect([1, 2, 3, 4, 5]);

inserted.splice(2, 1, [10, 11]).all();
// => [3]

inserted.all();
// => [1, 2, 10, 11, 4, 5]

const last = collect([1, 2, 3, 4, 5]);

last.splice(-2).all();
// => [4, 5]

last.all();
// => [1, 2, 3]

▶ Try it · collect(items).splice(offset, length)

Result{"removed":[3],"left":[1,2,4,5]}

split ​

Break the collection into the given number of groups.

Laravel: split()

The groups are as even as possible, and the first ones take the extra items: seven items in three groups make groups of 3, 2 and 2. Each group is a collection, so use toArray() to read them all at once. With more groups than items, each item gets a group of its own. A number below 1 throws an InvalidArgumentException. To fill each group before starting the next, use splitIn.

js
import { collect } from "@tolki/collection";

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

collect([1, 2, 3]).split(5).toArray();
// => [[1], [2], [3]]

collect({ a: 1, b: 2, c: 3 }).split(2).toArray();
// => [{ a: 1, b: 2 }, { c: 3 }]

collect([1, 2, 3, 4, 5, 6, 7]).split(3).toArray();
// => [[1, 2, 3], [4, 5], [6, 7]]

collect([1]).split(0);
// => throws InvalidArgumentException

▶ Try it · collect(items).split(numberOfGroups)

Result[[1,2],[3,4],[5]]

splitIn ​

Break the collection into the given number of groups, filling each group before starting the next.

Laravel: splitIn()

Every group but the last is full, and the last gets what is left. A number below 1 throws an InvalidArgumentException. Like chunk, each group keeps its items' keys, so a later group of a list starts at its original position. Laravel's docs leave those keys out. Use values on each group to renumber it.

js
import { collect } from "@tolki/collection";

const numbers = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

numbers.splitIn(3).toArray();
// => [
//   { 0: 1, 1: 2, 2: 3, 3: 4 },
//   { 4: 5, 5: 6, 6: 7, 7: 8 },
//   { 8: 9, 9: 10 },
// ]

numbers
  .splitIn(3)
  .map((group) => group.values().all())
  .all();
// => [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]

collect([1]).splitIn(0);
// => throws InvalidArgumentException

▶ Try it · collect(items).splitIn(numberOfGroups)

Result[{"0":1,"1":2,"2":3,"3":4},{"4":5,"5":6,"6":7,"7":8},{"8":9,"9":10}]

sum ​

Get the sum of the items, or of the values a key or callback picks from them.

Laravel: sum()

Pass a key, which may be a dot-notation path, or a callback to choose the value to add from each item. An empty collection gives 0. Numeric strings are added as numbers, null counts as 0 and true as 1. A value that cannot be added, such as a non-numeric string or an array, throws a TypeError.

js
import { collect } from "@tolki/collection";

collect([1, 2, 3, 4, 5]).sum();
// => 15

collect([
  { name: "JavaScript: The Good Parts", pages: 176 },
  { name: "JavaScript: The Definitive Guide", pages: 1096 },
]).sum("pages");
// => 1272

collect([
  { name: "Chair", colors: ["Black"] },
  { name: "Desk", colors: ["Black", "Mahogany"] },
  { name: "Bookcase", colors: ["Red", "Beige", "Brown"] },
]).sum((product) => product.colors.length);
// => 6

collect(["1", "2.5", 3]).sum();
// => 6.5

collect([1, null, 2]).sum();
// => 3

collect([true, true, false]).sum();
// => 2

collect([]).sum();
// => 0

collect(["a", 1]).sum();
// => throws TypeError

▶ Try it · collect(items).sum(key)

Result1272

Symbol.iterator ​

JS only

Make the collection iterable, so for...of, spreading and Array.from() read its values.

It gives the iterator that getIterator returns, so the values come in the collection's order and the keys are left out. See JavaScript-only additions.

js
import { collect } from "@tolki/collection";

[...collect([1, 2])];
// => [1, 2]

[...collect({ a: 1, b: 2 })];
// => [1, 2]

Array.from(collect({ a: 1, b: 2 }));
// => [1, 2]

const seen = [];

for (const value of collect(["x", "y"])) {
  seen.push(value);
}

seen;
// => ["x", "y"]

▶ Try it · [...collect(items)]

Result[1,2]

Symbol.toPrimitive ​

JS only

Convert the collection to a primitive: its count where a number is wanted, and its JSON string everywhere else.

+collection and Number(collection) give the number of items. A template string, String(collection) and collection + "" give what toString returns. See JavaScript-only additions.

js
import { collect } from "@tolki/collection";

const numbers = collect([1, 2, 3]);

+numbers;
// => 3

Number(numbers);
// => 3

`${numbers}`;
// => "[1,2,3]"

collect({ a: 1 }) + "";
// => '{"a":1}'

▶ Try it · +collect(items) and `${collect(items)}`

Result{"number":3,"text":"[1,2,3]"}

take ​

Take the first or last given number of items.

Laravel: take()

A positive number takes items from the start. A negative number takes that many from the end. The same operation on plain arrays and objects is in the utilities list.

INFO

A list stays a list, so the items taken from the end are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

const numbers = collect([0, 1, 2, 3, 4, 5]);

numbers.take(3).all();
// => [0, 1, 2]

numbers.take(-2).all();
// => [4, 5]

collect({ a: 1, b: 2, c: 3 }).take(-2).all();
// => { b: 2, c: 3 }

▶ Try it · collect(items).take(limit)

Result[0,1,2]

takeUntil ​

Take items until one passes a test or equals a value.

Laravel: takeUntil()

Pass a callback, which receives the item and its key, or a value. A value is compared strictly, so "3" does not match 3. The items before the one that stops it are returned. If nothing stops it, all the items are returned. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

const numbers = collect([1, 2, 3, 4]);

numbers.takeUntil((item) => item >= 3).all();
// => [1, 2]

numbers.takeUntil(3).all();
// => [1, 2]

numbers.takeUntil("3").all();
// => [1, 2, 3, 4]

numbers.takeUntil(9).all();
// => [1, 2, 3, 4]

collect({ a: 1, b: 2, c: 3 })
  .takeUntil((value, key) => key === "c")
  .all();
// => { a: 1, b: 2 }

▶ Try it · collect(items).takeUntil(callback)

Result[1,2]

takeWhile ​

Take items while a test passes or a value matches.

Laravel: takeWhile()

Pass a callback, which receives the item and its key, or a value. A value is compared strictly, so "1" does not match 1. The items before the first one that fails are returned. If the test never fails, all the items are returned. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

const numbers = collect([1, 2, 3, 4]);

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

collect([1, 1, 2, 2, 3, 3]).takeWhile(1).all();
// => [1, 1]

collect([1, 1, 2]).takeWhile("1").all();
// => []

numbers.takeWhile(() => true).all();
// => [1, 2, 3, 4]

collect({ a: 1, b: 2, c: 3 })
  .takeWhile((value, key) => key !== "c")
  .all();
// => { a: 1, b: 2 }

▶ Try it · collect(items).takeWhile(callback)

Result[1,2]

tap ​

Pass the collection to a callback, then return the collection itself.

Laravel: tap()

Use it to look at the collection in the middle of a chain without changing the chain. What the callback returns is ignored. To use the callback's result instead, use pipe.

js
import { collect } from "@tolki/collection";

const seen = [];

collect([2, 4, 3, 1, 5])
  .sort()
  .tap((collection) => {
    seen.push(collection.values().all());
  })
  .shift();
// => 1

seen;
// => [[1, 2, 3, 4, 5]]

const numbers = collect([1, 2]);

numbers.tap(() => [9]) === numbers;
// => true

▶ Try it · collect(items).sort().tap(callback)

Result{"seen":[[1,2,3,4,5]],"result":[1,2,3,4,5]}

times ​

Create a collection by calling a callback a given number of times.

Laravel: times()

The static times method calls the callback with the numbers 1 up to the count, and collects what it returns. Without a callback it collects the numbers themselves. A count below 1 gives an empty collection.

js
import { Collection } from "@tolki/collection";

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

Collection.times(3).all();
// => [1, 2, 3]

Collection.times(0).all();
// => []

▶ Try it · Collection.times(count, callback)

Result[9,18,27,36,45]

toArray ​

Get the items as a plain array, or as a plain object for a keyed collection.

Laravel: toArray()

It returns a copy. An item that is itself a collection, or any other object with its own toArray() method, is converted too, while a plain object is left as it is. To get the items as they are, with nested collections intact, use all.

js
import { collect, Collection } from "@tolki/collection";

collect({ name: "Desk", price: 200 }).toArray();
// => { name: "Desk", price: 200 }

collect([collect([1, 2]), collect({ a: 1 })]).toArray();
// => [[1, 2], { a: 1 }]

collect([collect([1, 2])]).all()[0] instanceof Collection;
// => true

▶ Try it · collect(items).toArray()

Result{"name":"Desk","price":200}

toBase ​

Get a plain Collection that holds a copy of the items.

Called on an instance of a subclass, it gives back the base class, so the subclass's own methods and behaviour are left behind. Changing the copy leaves the original as it was.

js
import { Collection } from "@tolki/collection";

class Users extends Collection {}

const users = Users.make([1, 2]);

users instanceof Users;
// => true

users.toBase() instanceof Users;
// => false

const base = users.toBase();

base.push(3);

base.all();
// => [1, 2, 3]

users.all();
// => [1, 2]

▶ Try it · ExampleUsers.make(items).toBase()

Result{"isUsers":true,"baseIsUsers":false,"items":[1,2]}

toJson ​

Get the items as a JSON string.

Laravel: toJson()

It takes the arguments of JSON.stringify() in place of PHP's flags: a replacer, which is a function or a list of keys, and a number or string to indent with (see JavaScript-only additions). It writes / and non-ASCII characters as they are (see Values). For a pretty-printed string, use toPrettyJson. To give JSON.stringify() the items yourself, see toJSON.

js
import { collect } from "@tolki/collection";

collect({ name: "Desk", price: 200 }).toJson();
// => '{"name":"Desk","price":200}'

collect([1, 2, 3]).toJson();
// => "[1,2,3]"

collect({ a: 1, b: 2 }).toJson(["a"]);
// => '{"a":1}'

collect({ a: 1 }).toJson(null, 2);
// => '{\n  "a": 1\n}'

▶ Try it · collect(items).toJson(replacer, space)

Result"{\"name\":\"Desk\",\"price\":200}"

toJSON ​

JS only

Give JSON.stringify() the items to encode.

JSON.stringify() calls this method on any object that has one, so a collection nested in other data is encoded as its items. It returns what jsonSerialize returns, and toJson is the method to call yourself when you want the string. See JavaScript-only additions.

js
import { collect } from "@tolki/collection";

JSON.stringify(collect([1, 2]));
// => "[1,2]"

JSON.stringify({ users: collect([{ id: 1 }]) });
// => '{"users":[{"id":1}]}'

collect({ a: 1 }).toJSON();
// => { a: 1 }

▶ Try it · JSON.stringify({ items: collect(items) })

Result"{\"items\":[{\"id\":1}]}"

toPrettyJson ​

Get the items as a JSON string with line breaks and indentation.

Laravel: toPrettyJson()

It indents with 4 spaces by default. Like toJson, it takes a replacer and, in place of PHP's flags, the indent to use.

js
import { collect } from "@tolki/collection";

collect({ name: "Desk", price: 200 }).toPrettyJson();
// => '{\n    "name": "Desk",\n    "price": 200\n}'

collect({ name: "Desk", price: 200 }).toPrettyJson(null, 2);
// => '{\n  "name": "Desk",\n  "price": 200\n}'

▶ Try it · collect(items).toPrettyJson(replacer, space)

Result"{\n \"name\": \"Desk\",\n \"price\": 200\n}"

toString ​

Get the items as a JSON string, which is what casting the collection to a string gives.

It returns the same string as toJson with no arguments. After escapeWhenCastingToString, the string is HTML-escaped. Symbol.toPrimitive uses it for string casts.

js
import { collect } from "@tolki/collection";

collect([1, 2, 3]).toString();
// => "[1,2,3]"

String(collect({ a: 1 }));
// => '{"a":1}'

collect(["<b>"]).escapeWhenCastingToString().toString();
// => '[&quot;&lt;b&gt;&quot;]'

▶ Try it · collect(items).toString()

Result"{\"a\":1}"

transform ​

Replace each item with the value the callback returns for it.

Laravel: transform()

The callback receives the item and its key. To get a new collection and leave this one alone, use map.

WARNING

Unlike most other collection methods, transform does not return a new modified collection; it modifies and returns the collection it is called on.

js
import { collect } from "@tolki/collection";

const items = collect([1, 2, 3, 4, 5]);

items.transform((item, key) => item * 2).all();
// => [2, 4, 6, 8, 10]

items.all();
// => [2, 4, 6, 8, 10]

items.transform((item) => item + 1) === items;
// => true

collect({ a: 1, b: 2 })
  .transform((value, key) => value + key)
  .all();
// => { a: "1a", b: "2b" }

▶ Try it · collect(items).transform(callback)

Result[2,4,6,8,10]

undot ​

Expand a collection with "dot" notation keys into a multi-dimensional one.

Laravel: undot()

A key with no dot stays as it is, so a list comes back unchanged. For the reverse, see dot. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

collect({
  "name.first_name": "Marie",
  "name.last_name": "Valentine",
  "address.line_1": "2992 Eagle Drive",
  "address.suburb": "Detroit",
})
  .undot()
  .toArray();
// => {
//   name: { first_name: "Marie", last_name: "Valentine" },
//   address: { line_1: "2992 Eagle Drive", suburb: "Detroit" },
// }

collect([1, 2]).undot().all();
// => [1, 2]

▶ Try it · collect(items).undot()

Result{"name":{"first_name":"Marie","last_name":"Valentine"},"address":{"suburb":"Detroit"}}

union ​

Add the given items to the collection, keeping the collection's own value for any key it already has.

Laravel: union()

The given items only fill keys the collection lacks. The collection is not changed: you get a new one. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

collect({ 1: ["a"], 2: ["b"] })
  .union({ 3: ["c"], 1: ["d"] })
  .all();
// => { 1: ["a"], 2: ["b"], 3: ["c"] }

collect([1, 2]).union([3, 4, 5]).all();
// => [1, 2, 5]

▶ Try it · collect(items).union(other)

Result{"1":["a"],"2":["b"],"3":["c"]}

unique ​

Get the items that are not repeated, keeping the first of each.

Laravel: unique()

Pass a key or a path to compare items by that value, or a callback that returns the value to compare. Values are compared loosely, so 1 and "1" count as the same: see Loose and strict comparison, and Values for the edge cases. To compare strictly, use uniqueStrict.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

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

collect([1, "1", 2]).unique().all();
// => [1, 2]

const products = 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" },
]);

products.unique("brand").pluck("name").all();
// => ["iPhone 6", "Galaxy S6"]

products
  .unique((item) => item.brand + item.type)
  .pluck("name")
  .all();
// => ["iPhone 6", "Apple Watch", "Galaxy S6", "Galaxy Gear"]

collect({ a: 1, b: 1, c: 2 }).unique().all();
// => { a: 1, c: 2 }

▶ Try it · collect(items).unique(key)

Result["iPhone 6","Galaxy S6"]

uniqueStrict ​

Get the items that are not repeated, comparing values strictly.

Laravel: uniqueStrict()

It takes the same arguments as unique, but 1 and "1" are different values: see Loose and strict comparison.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

collect([1, "1", 1, 2]).uniqueStrict().all();
// => [1, "1", 2]

collect([{ id: 1 }, { id: "1" }, { id: 1 }])
  .uniqueStrict("id")
  .all();
// => [{ id: 1 }, { id: "1" }]

▶ Try it · collect(items).uniqueStrict(key)

Result[1,"1",2]

unless ​

Run the callback unless the given value is truthy.

Laravel: unless()

The callback receives the collection and the value, and unless returns what the callback returns. If that is null or undefined, it returns the collection. A third argument is a callback to run when the value is truthy. The value may also be a function, which is called with the collection and whose result is tested. Truthiness is PHP's: see Truthiness. Laravel's one-argument form is not available: see Not portable. The inverse is when.

js
import { collect } from "@tolki/collection";

const items = collect([1, 2, 3]);

items.unless(true, (collection) => collection.push(4));
items.unless(false, (collection) => collection.push(5));

items.all();
// => [1, 2, 3, 5]

const other = collect([1, 2, 3]);

other.unless(
  true,
  (collection) => collection.push(4),
  (collection) => collection.push(5),
);

other.all();
// => [1, 2, 3, 5]

collect([1, 2, 3])
  .unless(false, (collection) => collection.map((item) => item * 2))
  .all();
// => [2, 4, 6]

collect([1])
  .unless(
    (collection) => collection.count() > 2,
    (collection) => collection.push(4),
  )
  .all();
// => [1, 4]

▶ Try it · collect(items).unless(value, callback, defaultCallback)

Result[1,2,3,4]

unlessEmpty ​

Run the callback unless the collection is empty.

Laravel: unlessEmpty()

It is an alias of whenNotEmpty. The callback receives the collection and true. A second callback runs when the collection is empty.

js
import { collect } from "@tolki/collection";

const names = collect(["Michael", "Tom"]);

names.unlessEmpty((collection) => collection.push("Adam"));

names.all();
// => ["Michael", "Tom", "Adam"]

const empty = collect([]);

empty.unlessEmpty(
  (collection) => collection.push("Adam"),
  (collection) => collection.push("Taylor"),
);

empty.all();
// => ["Taylor"]

▶ Try it · collect(items).unlessEmpty(callback, defaultCallback)

Result["Michael","Tom","Adam"]

unlessNotEmpty ​

Run the callback unless the collection is not empty.

Laravel: unlessNotEmpty()

It is an alias of whenEmpty. The callback receives the collection and true. A second callback runs when the collection is not empty.

js
import { collect } from "@tolki/collection";

const names = collect(["Michael", "Tom"]);

names.unlessNotEmpty((collection) => collection.push("Adam"));

names.all();
// => ["Michael", "Tom"]

const empty = collect([]);

empty.unlessNotEmpty(
  (collection) => collection.push("Adam"),
  (collection) => collection.push("Taylor"),
);

empty.all();
// => ["Adam"]

▶ Try it · collect(items).unlessNotEmpty(callback, defaultCallback)

Result["Adam"]

unshift ​

Add one or more items to the beginning of the collection.

Each item becomes one new item, so an array you pass is added whole. On a keyed collection the new items get the integer keys 0, 1 and so on, ahead of the existing ones. The same operation on plain arrays and objects is in the utilities list. To add one item under a key, use prepend.

WARNING

Unlike most other collection methods, unshift does not return a new modified collection; it modifies and returns the collection it is called on.

js
import { collect } from "@tolki/collection";

const items = collect([3, 4]);

items.unshift(1, 2).all();
// => [1, 2, 3, 4]

items.all();
// => [1, 2, 3, 4]

items.unshift(0) === items;
// => true

collect([4, 5, 6]).unshift(["a", "b", "c"]).all();
// => [["a", "b", "c"], 4, 5, 6]

collect({ b: 2 }).unshift({ a: 1 }).all();
// => { 0: { a: 1 }, b: 2 }

▶ Try it · collect(items).unshift(value)

Result[1,2,3]

unwrap ​

The static unwrap method gets the items of a collection, and gives any other value back as it is.

Laravel: unwrap()

It is the reverse of wrap.

js
import { Collection, collect } from "@tolki/collection";

Collection.unwrap(collect(["John Doe"]));
// => ["John Doe"]

Collection.unwrap(collect({ name: "John Doe" }));
// => { name: "John Doe" }

Collection.unwrap(["John Doe"]);
// => ["John Doe"]

Collection.unwrap("John Doe");
// => "John Doe"

▶ Try it · Collection.unwrap(value)

Result["John Doe"]

value ​

Get one value from the first item that holds the key.

Laravel: value()

The key may be a path: see Dot Notation. Items that lack the key are skipped. When no item holds it, you get the default, which may be a function that returns it, or null if you pass none. A null key always gives null.

js
import { collect } from "@tolki/collection";

const products = collect([
  { product: "Desk", price: 200 },
  { product: "Speaker", price: 400 },
]);

products.value("price");
// => 200

collect([{ name: "Desk" }, { price: 400 }]).value("price");
// => 400

collect([{ details: { price: 200 } }]).value("details.price");
// => 200

products.value("weight", 30);
// => 30

products.value("weight", () => 25);
// => 25

collect([]).value("price");
// => null

collect([{ a: 1 }]).value(null);
// => null

▶ Try it · collect(items).value(key, defaultValue)

Result200

values ​

Get the items as a list, with the keys reset to consecutive integers.

Laravel: values()

The items keep their order. The same operation on plain arrays and objects is in the utilities list.

js
import { collect } from "@tolki/collection";

collect({
  10: { product: "Desk", price: 200 },
  11: { product: "Speaker", price: 400 },
})
  .values()
  .all();
// => [
//   { product: "Desk", price: 200 },
//   { product: "Speaker", price: 400 },
// ]

collect({ a: 1, b: 2 }).values().all();
// => [1, 2]

▶ Try it · collect(items).values()

Result[{"product":"Desk","price":200},{"product":"Speaker","price":400}]

when ​

Run the callback when the given value is truthy.

Laravel: when()

The callback receives the collection and the value, and when returns what the callback returns. If that is null or undefined, it returns the collection. A third argument is a callback to run when the value is falsy. The value may also be a function, which is called with the collection and whose result is tested. Truthiness is PHP's: see Truthiness. Laravel's one-argument form is not available: see Not portable. The inverse is unless.

js
import { collect } from "@tolki/collection";

const items = collect([1, 2, 3]);

items.when(true, (collection) => collection.push(4));
items.when(false, (collection) => collection.push(5));

items.all();
// => [1, 2, 3, 4]

const other = collect([1, 2, 3]);

other.when(
  false,
  (collection) => collection.push(4),
  (collection) => collection.push(5),
);

other.all();
// => [1, 2, 3, 5]

collect([1, 2, 3])
  .when(true, (collection) => collection.map((item) => item * 2))
  .all();
// => [2, 4, 6]

collect([1, 2, 3])
  .when(
    (collection) => collection.count() > 2,
    (collection, value) => collection.push(value),
  )
  .all();
// => [1, 2, 3, true]

▶ Try it · collect(items).when(value, callback, defaultCallback)

Result[1,2,3,4]

whenEmpty ​

Run the callback when the collection is empty.

Laravel: whenEmpty()

The callback receives the collection and true. A second callback runs when the collection is not empty. Like when, it returns what the callback returns, or the collection if that is null or undefined. The inverse is whenNotEmpty.

js
import { collect } from "@tolki/collection";

const names = collect(["Michael", "Tom"]);

names.whenEmpty((collection) => collection.push("Adam"));

names.all();
// => ["Michael", "Tom"]

const empty = collect([]);

empty.whenEmpty((collection) => collection.push("Adam"));

empty.all();
// => ["Adam"]

const both = collect(["Michael", "Tom"]);

both.whenEmpty(
  (collection) => collection.push("Adam"),
  (collection) => collection.push("Taylor"),
);

both.all();
// => ["Michael", "Tom", "Taylor"]

▶ Try it · collect(items).whenEmpty(callback, defaultCallback)

Result["Adam"]

whenNotEmpty ​

Run the callback when the collection is not empty.

Laravel: whenNotEmpty()

The callback receives the collection and true. A second callback runs when the collection is empty. Like when, it returns what the callback returns, or the collection if that is null or undefined. The inverse is whenEmpty.

js
import { collect } from "@tolki/collection";

const names = collect(["Michael", "Tom"]);

names.whenNotEmpty((collection) => collection.push("Adam"));

names.all();
// => ["Michael", "Tom", "Adam"]

const empty = collect([]);

empty.whenNotEmpty((collection) => collection.push("Adam"));

empty.all();
// => []

const both = collect([]);

both.whenNotEmpty(
  (collection) => collection.push("Adam"),
  (collection) => collection.push("Taylor"),
);

both.all();
// => ["Taylor"]

▶ Try it · collect(items).whenNotEmpty(callback, defaultCallback)

Result["Michael","Tom","Adam"]

where ​

Filter the collection by a key and value.

Laravel: where()

Pass a key and a value, or a key, an operator and a value. The key may be a path: see Dot Notation. The operators are ===, !==, !=, ==, =, <>, >, <, >= and <=. With a key alone, it keeps the items where that key is truthy. Values are compared loosely, so 100 matches "100": see Loose and strict comparison. For strict comparison, use whereStrict; for null, use whereNull and whereNotNull.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

const products = collect([
  { product: "Desk", price: 200 },
  { product: "Chair", price: 100 },
  { product: "Bookcase", price: 150 },
  { product: "Door", price: 100 },
]);

products.where("price", 100).all();
// => [
//   { product: "Chair", price: 100 },
//   { product: "Door", price: 100 },
// ]

products.where("price", ">", 100).pluck("product").all();
// => ["Desk", "Bookcase"]

collect([{ price: "100" }, { price: 100 }, { price: 99 }])
  .where("price", 100)
  .all();
// => [{ price: "100" }, { price: 100 }]

collect([{ v: 1 }, { v: 0 }, { v: "a" }])
  .where("v")
  .all();
// => [{ v: 1 }, { v: "a" }]

▶ Try it · collect(items).where(key, operator, value)

Result[{"name":"Jim","platform":"Mac"},{"name":"Sally","platform":"Mac"}]

whereBetween ​

Filter the collection to the items whose value at a key lies within a range.

Laravel: whereBetween()

Pass the key and a list of the lowest and highest values. Both ends are included. The key may be a path: see Dot Notation. The bounds may also be a collection: see JavaScript-only additions.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

const products = collect([
  { product: "Desk", price: 200 },
  { product: "Chair", price: 80 },
  { product: "Bookcase", price: 150 },
  { product: "Pencil", price: 30 },
  { product: "Door", price: 100 },
]);

products.whereBetween("price", [100, 200]).pluck("product").all();
// => ["Desk", "Bookcase", "Door"]

products
  .whereBetween("price", collect([30, 80]))
  .pluck("product")
  .all();
// => ["Chair", "Pencil"]

▶ Try it · collect(items).whereBetween(key, values)

Result[{"product":"Desk","price":200},{"product":"Bookcase","price":150},{"product":"Door","price":100}]

whereIn ​

Filter the collection to the items whose value at a key is in the given list.

Laravel: whereIn()

The list may be an array, an object or a collection, and only its values count. Values are compared loosely, so 150 matches "150": see Loose and strict comparison. For strict comparison, use whereInStrict. The inverse is whereNotIn.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

const products = collect([
  { product: "Desk", price: 200 },
  { product: "Chair", price: 100 },
  { product: "Bookcase", price: 150 },
  { product: "Door", price: 100 },
]);

products.whereIn("price", [150, 200]).all();
// => [
//   { product: "Desk", price: 200 },
//   { product: "Bookcase", price: 150 },
// ]

collect([{ price: "150" }, { price: 150 }, { price: 2 }])
  .whereIn("price", [150])
  .all();
// => [{ price: "150" }, { price: 150 }]

▶ Try it · collect(items).whereIn(key, values)

Result[{"product":"Desk","price":200},{"product":"Bookcase","price":150}]

whereInstanceOf ​

Filter the collection to the items that are instances of a class.

Laravel: whereInstanceOf()

Pass a class, an array of classes or an object whose values are classes. An item is kept when it is an instance of any of them.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

class User {}
class Post {}

const names = (items) => items.all().map((item) => item.constructor.name);

names(collect([new User(), new Post(), new User()]).whereInstanceOf(User));
// => ["User", "User"]

names(collect([new User(), new Post()]).whereInstanceOf([User, Post]));
// => ["User", "Post"]

whereInStrict ​

Filter the collection to the items whose value at a key is in the given list, comparing strictly.

Laravel: whereInStrict()

It takes the same arguments as whereIn, but 150 and "150" are different values: see Loose and strict comparison.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

collect([{ price: "150" }, { price: 150 }, { price: 2 }])
  .whereInStrict("price", [150])
  .all();
// => [{ price: 150 }]

▶ Try it · collect(items).whereInStrict(key, values)

Result[{"price":150}]

whereNotBetween ​

Filter the collection to the items whose value at a key lies outside a range.

Laravel: whereNotBetween()

Pass the key and a list of the lowest and highest values. Values equal to either end are not kept. The inverse is whereBetween, and the bounds may be a collection there too: see JavaScript-only additions.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

const products = collect([
  { product: "Desk", price: 200 },
  { product: "Chair", price: 80 },
  { product: "Bookcase", price: 150 },
  { product: "Pencil", price: 30 },
  { product: "Door", price: 100 },
]);

products.whereNotBetween("price", [100, 200]).pluck("product").all();
// => ["Chair", "Pencil"]

▶ Try it · collect(items).whereNotBetween(key, values)

Result[{"product":"Chair","price":80},{"product":"Pencil","price":30}]

whereNotIn ​

Filter the collection to the items whose value at a key is not in the given list.

Laravel: whereNotIn()

The list may be an array, an object or a collection, and only its values count. Values are compared loosely, so 150 matches "150": see Loose and strict comparison. For strict comparison, use whereNotInStrict. The inverse is whereIn.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

const products = collect([
  { product: "Desk", price: 200 },
  { product: "Chair", price: 100 },
  { product: "Bookcase", price: 150 },
  { product: "Door", price: 100 },
]);

products.whereNotIn("price", [150, 200]).all();
// => [
//   { product: "Chair", price: 100 },
//   { product: "Door", price: 100 },
// ]

collect([{ price: "150" }, { price: 150 }, { price: 2 }])
  .whereNotIn("price", [150])
  .all();
// => [{ price: 2 }]

▶ Try it · collect(items).whereNotIn(key, values)

Result[{"product":"Chair","price":100},{"product":"Door","price":100}]

whereNotInStrict ​

Filter the collection to the items whose value at a key is not in the given list, comparing strictly.

Laravel: whereNotInStrict()

It takes the same arguments as whereNotIn, but 150 and "150" are different values: see Loose and strict comparison.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

collect([{ price: "150" }, { price: 150 }, { price: 2 }])
  .whereNotInStrict("price", [150])
  .all();
// => [{ price: "150" }, { price: 2 }]

▶ Try it · collect(items).whereNotInStrict(key, values)

Result[{"price":"150"},{"price":2}]

whereNotNull ​

Filter the collection to the items whose value at a key is not null.

Laravel: whereNotNull()

Falsy values such as 0 and "" are kept. Leave the key out to test the items themselves. The key may be a path: see Dot Notation. A key whose value is undefined counts as null: see JavaScript-only additions. The inverse is whereNull.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

const items = collect([
  { name: "Desk" },
  { name: null },
  { name: "Bookcase" },
  { name: 0 },
  { name: "" },
]);

items.whereNotNull("name").all();
// => [{ name: "Desk" }, { name: "Bookcase" }, { name: 0 }, { name: "" }]

collect([1, null, 2]).whereNotNull().all();
// => [1, 2]

▶ Try it · collect(items).whereNotNull(key)

Result[{"name":"Desk"},{"name":"Bookcase"},{"name":0},{"name":""}]

whereNull ​

Filter the collection to the items whose value at a key is null.

Laravel: whereNull()

Only null matches: 0 and "" do not. Leave the key out to test the items themselves. The key may be a path: see Dot Notation. A key whose value is undefined counts as null: see JavaScript-only additions. The inverse is whereNotNull.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

const items = collect([
  { name: "Desk" },
  { name: null },
  { name: "Bookcase" },
  { name: 0 },
  { name: "" },
]);

items.whereNull("name").all();
// => [{ name: null }]

collect({ a: null, b: 0, c: null }).whereNull().all();
// => { a: null, c: null }

▶ Try it · collect(items).whereNull(key)

Result[{"name":null}]

whereStrict ​

Filter the collection by a key and value, comparing strictly.

Laravel: whereStrict()

It takes a key and a value, as where does, but 100 and "100" are different values: see Loose and strict comparison.

INFO

A list stays a list, so the items that remain are renumbered from 0. In Laravel they keep the keys they had. See Keys and order.

js
import { collect } from "@tolki/collection";

collect([{ price: "100" }, { price: 100 }, { price: 99 }])
  .whereStrict("price", 100)
  .all();
// => [{ price: 100 }]

▶ Try it · collect(items).whereStrict(key, value)

Result[{"price":100}]

wrap ​

The static wrap method puts the given value in a collection.

Laravel: wrap()

An array, a plain object or a Map gives a collection of its items. A collection gives a new collection of its items. null gives an empty collection. Any other value becomes the only item of a list. The same operation on plain arrays and objects is in the utilities list. The reverse is unwrap.

js
import { Collection, collect } from "@tolki/collection";

Collection.wrap("John Doe").all();
// => ["John Doe"]

Collection.wrap(["John Doe"]).all();
// => ["John Doe"]

Collection.wrap(collect(["John Doe"])).all();
// => ["John Doe"]

Collection.wrap({ name: "John Doe" }).all();
// => { name: "John Doe" }

Collection.wrap(null).all();
// => []

▶ Try it · Collection.wrap(value)

Result["John Doe"]

zip ​

Merge the values of the given items with the collection's values, position by position.

Laravel: zip()

You get a list with one collection per position, holding that position's value from the collection, then from each of the given items. The given items may be arrays, objects or collections, and only their values count. Pass several to add several values to each position. When one side is shorter, its missing values are null. Call toArray() to read the inner collections as arrays.

js
import { collect } from "@tolki/collection";

collect(["Chair", "Desk"]).zip([100, 200]).toArray();
// => [["Chair", 100], ["Desk", 200]]

collect([1, 2, 3]).zip(["a"], [true, false]).toArray();
// => [[1, "a", true], [2, null, false], [3, null, null]]

collect([1, 2]).zip(["a", "b", "c"]).toArray();
// => [[1, "a"], [2, "b"], [null, "c"]]

▶ Try it · collect(items).zip(other)

Result[["Chair",100],["Desk",200]]

Released under the MIT License.