Collection
Source:
shiva-fw/libs/collection/init.lua
Laravel-inspired collection class with fluent chaining, dot-notation key access, and conditional pipelines.
Availability
Collection and the collect() global helper are available in every shiva module (loaded by sh_init.lua). No import required.
Creating a Collection
Collection.new(items?)
local c = Collection.new({ 1, 2, 3 })collect(items?)
Shorthand global helper.
local c = collect({ 'a', 'b', 'c' })Retrieval
:all()
Return all items as a plain Lua table.
c:all() -- { 1, 2, 3 }:count()
Number of items.
c:count() -- 3:first(fn?)
First item, optionally matching a predicate.
c:first() -- 1
c:first(function(x) return x > 1 end) -- 2:last(fn?)
Last item, optionally matching a predicate.
c:last():get(index)
Item at a specific 1-based index.
c:get(2) -- 2:find(key, value)
Find the first item where item[key] == value (dot notation supported).
local player = players:find('id', 42):contains(key_or_fn, value?)
Returns true if any item matches. Pass a key+value or a predicate function.
c:contains(function(x) return x > 5 end)
players:contains('id', 42):isEmpty() / :isNotEmpty()
if c:isEmpty() then ... endFiltering
:filter(fn)
Keep items that match the predicate.
c:filter(function(x) return x % 2 == 0 end):reject(fn)
Keep items that do not match the predicate.
c:reject(function(x) return x < 0 end):where(key, op_or_value, value?)
Filter by key comparison. Operator is optional (defaults to ==).
players:where('job', 'police')
players:where('level', '>', 10):whereIn(key, values)
Keep items whose key is in the values array.
players:whereIn('job', { 'police', 'ems' }):whereNotNil(key)
Keep items where item[key] is not nil.
items:whereNotNil('metadata'):whereBetween(key, min, max)
Keep items where item[key] is between min and max (inclusive).
items:whereBetween('price', 100, 500)Transformation
:map(fn)
Transform each item.
c:map(function(x) return x * 2 end):flatMap(fn)
Map each item to an array, then flatten one level.
orders:flatMap(function(o) return o.items end):pluck(key)
Extract a single field from each item.
players:pluck('name') -- Collection of names:unique(key?)
Remove duplicate items, optionally by key.
c:unique()
players:unique('job'):keyBy(key)
Re-index the collection by a key field. Returns a plain table.
local byId = players:keyBy('id') -- table<id, player>:groupBy(key_or_fn)
Group items by key or function. Returns a table of Collections.
local byJob = players:groupBy('job'):chunk(size)
Split into a Collection of Collections of the given size.
c:chunk(3)Iteration
:each(fn)
Iterate over each item (side effects only, not chainable).
c:each(function(item, index) print(index, item) end)Aggregation
:sum(key?)
Sum all values or a numeric key.
c:sum()
orders:sum('total'):min(key?) / :max(key?)
c:min()
items:max('price'):avg(key?)
Average value.
orders:avg('total'):reduce(fn, initial?)
Reduce to a single value.
c:reduce(function(carry, item) return carry + item end, 0)Sorting
:sortBy(key_or_fn, direction?)
Sort by key or function. direction is 'asc' (default) or 'desc'.
players:sortBy('name')
players:sortBy('level', 'desc')Conditional Pipelines
:when(condition, fn)
Run fn(collection) only when condition is truthy.
c:when(isAdmin, function(col) return col:filter(...) end):unless(condition, fn)
Run fn(collection) only when condition is falsy.
c:unless(isEmpty, function(col) return col:sortBy('name') end)